C# 如何在给定所需排序层次结构的情况下对字符串列表进行自定义排序?

C# 如何在给定所需排序层次结构的情况下对字符串列表进行自定义排序?,c#,C#,我想以特定的方式对列表进行排序。下面是一个单元测试,显示了输入,具体方式(我称之为“层次结构”-请随意更正我的术语,以便我可以学习),以及所需的输出。代码应该是自解释的 [Test] public void CustomSortByHierarchy() { List<string> input = new List<string>{"TJ", "DJ", "HR", "HR", "TJ"}; List<string> hierarchy =

我想以特定的方式对
列表进行排序。下面是一个单元测试,显示了输入具体方式(我称之为“层次结构”-请随意更正我的术语,以便我可以学习),以及所需的输出。代码应该是自解释的

[Test]
public void CustomSortByHierarchy()
{
    List<string> input = new List<string>{"TJ", "DJ", "HR", "HR", "TJ"};

    List<string> hierarchy = new List<string>{"HR", "TJ", "DJ" };

    List<string> sorted = input.Sort(hierarchy); // <-- does not compile. How do I sort by the hierarchy?

    // ...and if the sort worked as desired, these assert statements would return true:
    Assert.AreEqual("HR", sorted[0]);
    Assert.AreEqual("HR", sorted[1]);
    Assert.AreEqual("TJ", sorted[2]);
    Assert.AreEqual("TJ", sorted[3]);
    Assert.AreEqual("DJ", sorted[4]);
}
[测试]
public void CustomSortByHierarchy()
{
列表输入=新列表{“TJ”、“DJ”、“HR”、“HR”、“TJ”};
列表层次结构=新列表{“HR”、“TJ”、“DJ”};
List sorted=input.Sort(层次结构);//另一种方法:

var hierarchy = new Dictionary<string, int>{
    { "HR",  1},
    { "TJ",  2},
    { "DJ",  3} };

var sorted = strings.OrderBy(s => hierarchy[s]).ToList();
var层次结构=新字典{
{“HR”,1},
{“TJ”,2},
{“DJ”,3};
var sorted=strings.OrderBy(s=>hierarchy[s]).ToList();

有很多方法可以做到这一点

创建一个静态字典并不好——特别是当您有一个静态的值列表已经按照您想要的顺序排列时(即
list hierarchy=new list{“HR”、“TJ”、“DJ”};
)。静态字典的问题是它是静态的—要更改它,您必须重新编译您的程序—而且很容易出错—您可能键入错误的数字。最好动态创建字典。这样,您可以在运行时调整
层次结构
,并使用它对
输入进行排序

以下是创建字典的基本方法:

Dictionary<string, int> indices =
    hierarchy
        .Select((value, index) => new { value, index })
        .ToDictionary(x => x.value, x => x.index);
您需要决定是从列表中删除缺少的项,还是将它们连接到列表的末尾

要删除,请执行以下操作:

List<string> sorted =
    input
        .Where(x => indices.ContainsKey(x))
        .OrderBy(x => indices[x])
        .ToList();
List<string> sorted =
    input
        .OrderBy(x => indices.ContainsKey(x) ? indices[x] : int.MaxValue)
        .ThenBy(x => x) // groups missing items together and is optional
        .ToList();
或者这个:

ILookup<string, string> lookup = input.ToLookup(x => x);
List<string> sorted = hierarchy.SelectMany(x => lookup[x]).ToList();
ILookup lookup=input.ToLookup(x=>x);
List sorted=hierarchy.SelectMany(x=>lookup[x]).ToList();

就我个人而言,我喜欢最后一条。它是一条两行线,完全不依赖于指数。

为你的问题提供单元测试是一个非常好的主意。更多的人应该这样做。我完全同意。如果有人这样做,那么帮助他们就容易多了。@sapbucket-请不要为你的问题添加答案。如果你有答案,请添加我t作为答案。欢迎您回答自己的问题。如果其他人的答案是正确的,不接受您的答案是一种良好的礼仪。如果您想将您的答案作为答案发布,您可以在“修订”链接中找到来源。这很好。请参阅原始发布中的我的编辑以获得完整的解决方案。
List<string> sorted =
    input
        .OrderBy(x => indices.ContainsKey(x) ? indices[x] : int.MaxValue)
        .ThenBy(x => x) // groups missing items together and is optional
        .ToList();
List<string> sorted =
(
    from x in input
    join y in hierarchy.Select((value, index) => new { value, index })
        on x equals y.value
    orderby y.index
    select x
).ToList();
ILookup<string, string> lookup = input.ToLookup(x => x);
List<string> sorted = hierarchy.SelectMany(x => lookup[x]).ToList();