根据其他列表的值对列表进行排序

时间:2018-04-18 16:11:36

标签: c#

我有两个列表:finalAnswersdraftAnswers,其中finalAnswers[i]draftAnswers[i]相关,且两者的大小相同。

我希望以某种方式对finalAnswers进行排序,i++元素draftAnswers[i].ID!=0出现在顶部,然后出现在其他元素中。

假设finalAnswers是:

finalAnswers[1].Name = "a";
finalAnswers[2].Name = "b";
finalAnswers[3].Name = "c";

draftAnswers中的相应元素:

draftAnswers[1].ID = 1;
draftAnswers[2].ID = 0;
draftAnswers[3].ID = 2;

一旦排序,finalAnswers就是:

finalAnswers[1].Name = "a";
finalAnswers[2].Name = "c";
finalAnswers[3].Name = "b";

我尝试使用通常的orderBy,但在这种情况下并不简单。任何建议都是有意义的。

更新 分类:

class A 
{
    public int id;
    public int tID;
    public int cID;
    public string Name;
}

值:

var finalAnswers = new List<A>() { new A() { id = 7, tID = 10, cID = 50, Name="Q1" }, 
                                   new A() { id = 8, tID = 20, cID = 30, Name="Q2" }, 
                                   new A() { id = 9, tID = 30, cID = 20, Name="Q3" } 
                                 };

var draftAnswers = new List<A>() { new A() { id = 1, tID = 10, cID = 50, Name="Q5" }, 
                                   new A() { id = 0, tID = 20, cID = 30, Name="Q2" }, 
                                   new A() { id = 1, tID = 30, cID = 20, Name="Q3" } 
                                 };

排序:

draftAnswers = draftAnswers.OrderBy(d=>d.id).ToList();
finalAnswers = finalAnswers.OrderBy(b => draftAnswers.FindIndex(a => a.tID == b.tID && a.cID == b.cID)).ToList();

OUTPUT(finalAnswer ID):

8
7
9

预期:

7
9
8

orderBy未按照按顺序排序 - dotNetFiddle

2 个答案:

答案 0 :(得分:0)

因此,您使用以下行对finalAnswers列表进行排序: 1

finalAnswers = finalAnswers.OrderBy(b => draftAnswers.FindIndex(a => a.tID == b.tID && a.cID == b.cID)).ToList();

它应该做什么,除了它有两个问题:

  • 没有考虑条件:draftAnswers[i].id!=0
  • 您要按属性值进行匹配,而不是根据原始要求进行匹配。

如果第二点对您来说不是问题,那么您可以按原样保留该行,只需更改使用ThenBy()方法对draftAnswers列表进行排序的方式,以便将其考虑在内排除.id == 0的项目:

draftAnswers = draftAnswers.OrderBy(d => d.id == 0).ThenBy(d => d.id).ToList();
finalAnswers = finalAnswers.OrderBy(b => draftAnswers.FindIndex(a => a.tID == b.tID &&
                                                                a.cID == b.cID)).ToList();

但是,我认为你没有理由继续使用两个单独的列表。您只需将它们合并到List<KeyValuePair> Key,其中draftAnswersValue项,finalAnswersThenBy()项。然后您可以使用var mixed = new List<KeyValuePair<A, A>>() { new KeyValuePair<A, A>(new A() { id = 1, tID = 10, cID = 50, Name = "Q5" }, // draft. new A() { id = 7, tID = 10, cID = 50, Name = "Q1" }), // final. new KeyValuePair<A, A>(new A() { id = 0, tID = 20, cID = 30, Name = "Q2" }, // draft. new A() { id = 8, tID = 20, cID = 30, Name = "Q2" }), // final. new KeyValuePair<A, A>(new A() { id = 1, tID = 10, cID = 50, Name = "Q5" }, // etc. new A() { id = 9, tID = 30, cID = 20, Name = "Q3" })}; mixed = mixed.OrderBy(a => a.Key.id == 0).ThenBy(a => a.Key.id).ToList(); Console.WriteLine("finalAnswers IDs:"); // Print the IDs of the values (finalAnswers). foreach (var item in mixed) Console.WriteLine(item.Value.id); Console.WriteLine("\ndraftAnswers IDs:"); // Print the IDs of the keys (draftAnswers). foreach (var item in mixed) Console.WriteLine(item.Key.id); 与上面相同的方式,以便根据您拥有的两个条件对列表进行排序。

以下内容可以正常使用:

.. b => finalAnswers.FindIndex ..

这将为两个列表提供所需的输出。 Try it online

希望有所帮助。

1 你有 - 似乎是 - 你小提琴中的拼写错误,你写的是.. b => draftAnswers.FindIndex ..而不是{{1这会产生完全不同的结果。只想清除它,以免其他人混淆。

答案 1 :(得分:0)

在您的评论中,您提到OrderBy应生成以下订单:1,1,0,但这将是OrderByDescendingOrderBy 升序,因此命令0,1,1。但无论您对draftAnswers进行排序的方式如何,结果都是(使用TId):20,10,30,或相反的30,10,20。请注意,使用OrderBy时,如果两个条目具有相同的值,则它们的相对位置保持不变。这就是你得到结果的原因。

因此,仅靠id字段排序,您无法获得预期结果。 可以获得该结果的一种方式(如果这是您想要的),是使用ThenBy进一步对cID字段进行排序:

draftAnswers = draftAnswers
    .OrderByDescending(d => d.id)
    .ThenByDescending(d => d.cID)
    .ToList();

finalAnswers = finalAnswers
    .OrderBy(b => draftAnswers.FindIndex(a => a.tID == b.tID && a.cID == b.cID))
    .ToList();