【问题标题】:Combining two generics of type Dictionary<string, List<Model>> into another of the same type将 Dictionary<string, List<Model>> 类型的两个泛型组合成另一个相同类型的泛型
【发布时间】:2019-06-23 22:27:29
【问题描述】:

我有两个 Dictionary&lt;string, List&lt;Person&gt;&gt; 类型的泛型,其中 Person 是:

Person {
   string FirstName;
   string LastName; 
   List<string> Aliases;
   string Address; 
}

其中一个泛型是“默认”,其中仅填写 FirstName 和 LastName。为简单起见,我将其称为“默认字典”...第二个字典(db 字典)填充了从 db 返回的值称呼。两个字典的键都是来自 person 对象的“FirstName”。

一些条件是:

  • 默认字典在列表中具有正确的“Person”对象顺序...它们不是按字母顺序或类似的顺序
  • 并非默认列表中的所有“Person”对象也会出现在 db 列表中(尽管 db 列表中的 person 对象总是在默认列表中匹配)
  • 虽然肯定有更好的方法来表示这些数据...字典类型必须保持原样,因为我将它们传递给使用 foreach 循环(嵌套表)的视图,其中键是主表并且列表是键下方的子表的行

我需要做的是用从数据库返回的数据为每个键填写默认字典列表的地址和别名列表...

我已经能够正确格式化默认和 db 字典并填充正确的数据(尽管 db 字典中的列表顺序不正确)...我还能够“过滤”将默认字典转换为仅包含 db 字典(过滤字典)中也存在的键的新字典...

我遇到的问题是使用从数据库返回的每个对象的地址和别名列表填充 Person 对象...我不能只替换列表,因为我需要保留 person 对象的顺序列表...这是我尝试的最后一件事的一些代码 sn-ps(将来自 db 的响应放入名为“responseList”的所有人员对象的列表中)...

    Dictionary<string, List<Person>> filteredDictionary = defaultDictionary.Where(x => firstNameList.Contains(x.Key)).ToDictionary(x => x.Key, y => y.Value);

    foreach (var entry in filteredDictionary)
    {
        var current = entry.Value.ToList();

        current.ForEach(x => responseList.Any(y => y.FirstName == x.FirstName));
        current.ForEach(x => x.Address = responseList.Select(y => y.Address));

    } 

我知道使用 LINQ...最好只创建一个新字典而不是修改现有字典...但我不确定如何将此信息放入一个新字典中以保留 List 中的 Persons下单……

任何帮助将不胜感激......我已经被这个问题困扰了一段时间。

【问题讨论】:

  • 我忘了补充一下,别名的 List 也是从数据库返回的,也需要复制过来
  • List 中的 Person's in List 的字典值顺序正确,抱歉不清楚
  • 你要找.Concat()吗?
  • 什么是“通用”?请注意,Dictionary 对象的成员没有顺序。您的 Person 类没有修饰符或 public 字段 - 您希望如何为其设置值?
  • 你说关键是Person对象的FirstName——这是否意味着有多个Person对象具有相同的FirstName,如果是,你怎么知道哪个一场比赛?如果不是,为什么Dictionary 中有List&lt;Person&gt;

标签: c# linq generics


【解决方案1】:

首先您应该知道,Dictionary&lt;TKey, TValue&gt; 并不能确保特定的顺序:

出于枚举的目的,字典中的每个项目都被视为表示值及其键的 KeyValuePair 结构。返回项目的顺序未定义。

尽管如此,当前的实现似乎以与给定顺序相同的顺序返回值。但他们不能保证这一点。如果您需要特定的订单,您应该使用SortedDictionary&lt;TKey, TValue&gt; 并提供所需的比较器。

在给出这些信息后,下面是一个示例,说明如何使用数据库字典中的值更新默认字典。

// Create some sample data, we can use
var persons = Enumerable
    .Range(1, 10)
    .Select(i => new Person
    {
        FirstName = $"FirstName {i}",
        LastName = Guid.NewGuid().ToString(),
        Address = $"Address {i}",
        Aliases = Enumerable
            .Range(i * 100, i)
            .Select(j => $"Alias {i} - {j}")
            .ToList()
    })
    .ToList();

// Create the default dict, (hopefully) ordered by Firstname
var defaultDict = persons.ToDictionary(
    person => person.FirstName,
    person => new Person
    {
        FirstName = person.FirstName,
        LastName = person.LastName
    });

// Create the default dict, (hopefully) ordered by Lastname
var dbDict = persons
    .OrderBy(person => person.LastName)
    .ToDictionary(person => person.FirstName);

Console.WriteLine("Default dictionary");
foreach (var person in defaultDict)
{
    Console.WriteLine($"{person.Value.FirstName} {person.Value.LastName} {person.Value.Address ?? "No address" }");
}

Console.WriteLine();
Console.WriteLine("DB dictionary");
foreach (var person in dbDict)
{
    Console.WriteLine($"{person.Value.FirstName} {person.Value.LastName} {person.Value.Address ?? "No address" }");
}

// Iterate over the db entries and update all default entries
foreach (var item in dbDict)
{
    if(defaultDict.TryGetValue(item.Key, out Person defaultPerson))
    {
        defaultPerson.Address = item.Value.Address;
        defaultPerson.Aliases = item.Value.Aliases.ToList();
    }
}

// Show updated default dictionary
Console.WriteLine();
Console.WriteLine("Updated default dictionary");
foreach (var person in defaultDict)
{
    Console.WriteLine($"{person.Value.FirstName} {person.Value.LastName} {person.Value.Address ?? "No address" }");
}

【讨论】:

  • 谢谢,根据您的回答,我能够解决我的问题!我在表述我的问题时遇到了一些问题,因为我试图遵守 NDA 的限制,对于造成的混乱,我深表歉意!
猜你喜欢
  • 1970-01-01
  • 2021-12-25
  • 2014-08-02
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
相关资源
最近更新 更多