合并两个列表并根据排名排列合并列表

时间:2017-02-20 15:43:36

标签: c# linq

我有两个列表,我正在尝试合并它们,合并后,我的列表应按排名按升序排列。

代码:

 public class Test
    {
        public int TestId { get; set; }
        public List<VariantsRank> VariantsRanks { get; set; }
    }

    public class VariantsRank
    {
        public int VariantId { get; set; }
        public string Name { get; set; }
        public int Rank { get; set; }
    }
    public class Class1
    {
        public void Process()
        {
            var List1 = new Test();
            List1.TestId = 100;
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 10, Name = "V1", Rank = 0 });
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 11, Name = "V2", Rank = 1 });
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 12, Name = "V3", Rank = 2 });
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 13, Name = "V4", Rank = 3 });
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 14, Name = "V5", Rank = 4 });

            List1.VariantsRanks.Add(new VariantsRank { VariantId = 15, Name = "V6", Rank = 5 });
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 16, Name = "V7", Rank = 6 });
            List1.VariantsRanks.Add(new VariantsRank { VariantId = 17, Name = "V8", Rank = 7 });

            var List2 = new Test();
            List2.TestId = 100;
            List2.VariantsRanks.Add(new VariantsRank { VariantId = 17, Name = "V8", Rank = 0 });
            List2.VariantsRanks.Add(new VariantsRank { VariantId = 15, Name = "V6", Rank = 1 });
            List2.VariantsRanks.Add(new VariantsRank { VariantId = 16, Name = "V7", Rank = 2 });
            List2.VariantsRanks.Concat(List1.VariantsRanks).GroupBy(x => x.VariantId).SelectMany(x => x.Take(1)).ToList();
        }
    }

输出我

VariantId = 10, Name = "V1", Rank = 0
VariantId = 11, Name = "V2", Rank = 1
VariantId = 12, Name = "V3", Rank = 2
VariantId = 13, Name = "V4", Rank = 3
VariantId = 14, Name = "V5", Rank = 4

VariantId = 15, Name = "V6", Rank = 5
VariantId = 16, Name = "V7", Rank = 6
VariantId = 17, Name = "V8", Rank = 7

预期输出:

List1.TestId = 100
[0] : VariantId = 10, Name = "V1", Rank = 0
[1] : VariantId = 11, Name = "V2", Rank = 1
[2] : VariantId = 12, Name = "V3", Rank = 2
[3] : VariantId = 13, Name = "V4", Rank = 3
[4] : VariantId = 14, Name = "V5", Rank = 4
[5] : VariantId = 17, Name = "V8", Rank = 5
[6] : VariantId = 15, Name = "V6", Rank = 6
[7] : VariantId = 16, Name = "V7", Rank = 7

现在我想合并2个列表和那些在list1中匹配的记录然后我想优先考虑列表2记录,所以列表2的v8,v6和v7应该替换列表1记录,即v6,v7和V8。

2 个答案:

答案 0 :(得分:3)

这是我想到的第一个解决方案:

var result=List1.VariantsRanks.Union(List2.VariantsRanks)
                .GroupBy(e=>e.VariantId)
                .Select(g=>g.OrderBy(e=>e.Rank).FirstOrDefault())
                .OrderBy(e=>e.RankId);

<强>解释

  1. 加入两个列表
  2. VariantId
  3. 的变体
  4. Rank订购每个小组,只保留第一个小组
  5. Rank
  6. 排序结果列表

答案 1 :(得分:3)

我理解它的方式,可以通过这种方式定义问题。给定两个有序列表,根据第二个列表中的顺序对第一个列表中的匹配项重新排序,从第一个列表末尾的第二个列表中添加不匹配的项。

我首先从第二个列表中准备一个有序匹配的队列:

var matchQueue = new Queue<VariantsRank>(
    from r2 in List2.VariantsRanks
    join r1 in List1.VariantsRanks on r2.VariantId equals r1.VariantId
    orderby r2.Rank
    select r2);

然后是匹配键的HashSet

var matchSet = new HashSet<int>(matchQueue.Select(r2 => r2.VariantId));

我们将按顺序处理第一个列表,然后每个元素将使用matchSet来确定是否匹配,如果是,则按顺序执行下一个匹配使用准备好的matchQueue

然后我们将按顺序追加第二个列表中不匹配的元素。最后,我们将迭代生成的序列(应该从前面的步骤中正确排序)并更新排名。

所有转换为LINQ的内容都是这样的:

var result = List1.VariantsRanks
    .OrderBy(r1 => r1.Rank)
    .Select(r1 => matchSet.Contains(r1.VariantId) ? matchQueue.Dequeue() : r1)
    .Concat(List2.VariantsRanks
    .Where(r2 => !matchSet.Contains(r2.VariantId))
    .OrderBy(r2 => r2.Rank))
    .Select((r, i) => new VariantsRank { VariantId = r.VariantId, Name = r.Name, Rank = i })
    .ToList();