我有两个列表,我正在尝试合并它们,合并后,我的列表应按排名按升序排列。
代码:
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。
答案 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);
<强>解释强>
VariantId
Rank
订购每个小组,只保留第一个小组Rank
答案 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();