Linq的小组词典

时间:2015-10-18 13:00:04

标签: c# linq list dictionary collections

我有两个var HeaderView = TemplateView.extend({ tagName: 'header', templateName: '#header-template', events: { 'click a.logout': 'logout' }, getContext: function () { return {authenticated: app.session.authenticated()}; }, logout: function (event) { event.preventDefault(); console.log('clicked'); app.session.delete(); window.location = '/'; } });

List<Dictionary<string, string>>

我想合并两个列表,并按键对值进行分组。结果是List<Dictionary<string, string>> ListdicA = new List<Dictionary<string, string>>(); Dictionary<string, string> dic1 = new Dictionary<string, string>(); dic1.Add("Type1", "1"); dic1.Add("Type2", "A"); dic1.Add("Type3", "X"); Dictionary<string, string> dic2 = new Dictionary<string, string>(); dic2.Add("Type1", "2"); dic2.Add("Type2", "B"); dic2.Add("Type3", "Y"); ListdicA.Add(dic1); ListdicA.Add(dic2); List<Dictionary<string, string>> ListdicB = new List<Dictionary<string, string>>(); Dictionary<string, string> dic3 = new Dictionary<string, string>(); dic3.Add("Type1", "1"); dic3.Add("Type2", "C"); dic3.Add("Type3", "X"); Dictionary<string, string> dic4 = new Dictionary<string, string>(); dic4.Add("Type1", "2"); dic4.Add("Type2", "D"); dic4.Add("Type3", "Z"); ListdicB.Add(dic3); ListdicB.Add(dic4); 。首先,我想合并两个列表:

List<Dictionary<string, List<string>>>

我希望用键对它进行分组,结果如下:

Type1 1
Type2 A
Type3 X

Type1 2
Type2 B
Type3 Y

Type1 1
Type2 C
Type3 X

Type1 2
Type2 D
Type3 Z

2 个答案:

答案 0 :(得分:1)

基于问题更新:

这非常复杂(至少对我而言)。我展示了这些步骤,并且我还将每个LINQ放在括号中,从而完成了这项工作。

1)你必须加入两个名单。 (ListdicA.Concat(ListdicB)

2)按每个词典Type1键的值对所有词典进行分组。(GroupBy(x => x["Type1"])

3)将所有项目IGrouping<string,Dictionary<string,string>>展开到KeyValuePair<string,string>SelectMany(y => y)

4)再次按Key键组键值,以便将相同键的值连接在一起(GroupBy(y => y.Key)

5)将IGrouping<string,KeyValuePair<string,string>>打包到IEnumerable<KeyValuePair<string,List<string>>>Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList()))

6)将IEnumerable<IEnumerable<KeyValuePair<string,List<string>>>>转换为IEnumerable<Dictionary<string,List<string>>>Select(x => x.ToDictionary(y => y.Key, y => y.Value))

7)最后将IEnumerable<Dictionary<string,List<string>>>转换为List<Dictionary<string, List<string>>>ToList()

string groupby = "Type1";

List<Dictionary<string, List<string>>> result =
    ListdicA.Concat(ListdicB).GroupBy(x => x[groupby]).Select(x =>
        x.SelectMany(y => y) // Put .Distinct() here to remove duplicates.(optional)
            .GroupBy(y => y.Key).Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
                .Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList();

foreach (var d in result)
{
    foreach (var k in d)
    {
        Console.Write(k.Key + " : ");
        foreach (var l in k.Value)
        {
            Console.Write(l + " ");
        }
        Console.WriteLine();
    }
}

输出

Type1 1 1
Type2 A C
Type3 X X

Type1 2 2
Type2 B D
Type3 Y Z

正如我在评论(内部代码)中所述,如果您删除该评论并将.Distinct()放在那里,则会删除重复项

List<Dictionary<string, List<string>>> result =
    ListdicA.Concat(ListdicB).GroupBy(x => x[groupby]).Select(x => x.SelectMany(y => y)
        .Distinct().GroupBy(y => y.Key)
            .Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
                .Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList();

将输出。

Type1 1
Type2 A C
Type3 X

Type1 2
Type2 B D
Type3 Y Z

如果您不想放松X,那么您需要自定义区别。你需要这门课。 (linq was taken and edited from here

public static class SomeMoreLinq
{
    public static IEnumerable<TSource> DistinctIf<TSource>
        (this IEnumerable<TSource> source, Func<TSource, bool> keySelector)
    {
        HashSet<TSource> seenKeys = new HashSet<TSource>();
        foreach (TSource element in source)
        {
            if (seenKeys.Add(element) || !keySelector(element))
            {
                yield return element;
            }
        }
    }
}

然后在查询中使用它。

List<Dictionary<string, List<string>>> result =
    ListdicA.Concat(ListdicB).GroupBy(x => x[groupby]).Select( x => x.SelectMany(y => y)
        .DistinctIf(y => y.Key == groupby).GroupBy(y => y.Key)
            .Select(y => new KeyValuePair<string, List<string>>(y.Key, y.Select(z => z.Value).ToList())))
                .Select(x => x.ToDictionary(y => y.Key, y => y.Value)).ToList();

将输出。

Type1 1
Type2 A C
Type3 X X

Type1 2
Type2 B D
Type3 Y Z

如果您有任何问题,请随时提出。

虽然这完全融化了我的想法,但这是一个很好的做法!。

答案 1 :(得分:0)

如果你这样做

ListdicA.Zip(ListdicB, (a,b) => a.Concat(b)
.GroupBy(x => x.Key)
.Select (g => new
              {
                   g.Key, 
                   Values = g.SelectMany(d => d.Value).Distinct()
              } ))

你得到这个结果:

Type 1   1
Type 2   A
         C
Type 3   X

Type 1   2
Type 2   B
         D
Type 3   Y
         Z

我不确定您的X X结果是故意还是错字。如果它有意,我应该添加一些逻辑。