【问题标题】:Sort a Nested string list in C#在 C# 中对嵌套字符串列表进行排序
【发布时间】:2015-09-13 06:50:15
【问题描述】:

我想要实现的是按字母顺序排列的嵌套列表。

例如我的意见:

fat, twat, gat    //Line 1
cat, hat, bat     // Line 2
twat, lack, rat   // Line 3

我希望输出是:

bat, cat, hat    // Line 2
fat, gat, twat   // Line 1
lack, rat, twat  // Line 3

如您所见,列表首先在内部排序,然后在外部排序。

我目前的实现是使用嵌套列表:

List<List<String>> testSort;

我已经设法使用这种方法对内部列表进行了排序:

    public static List<List<String>> sortList(List<List<String>> input)
    {
        input.ForEach(delegate (List<string> o)
        {
            o.Sort();
        });

        return input;
    }

我现在不确定如何对外面的列表进行排序。帮助将不胜感激!

提前致谢!

【问题讨论】:

    标签: c# sorting


    【解决方案1】:

    在每个内部列表已经排序之后,您可以使用 OrderBy() 根据每个列表的第一个元素对外部列表进行排序:

    input.ForEach(t => t.Sort());
    input = input.OrderBy(t => t.First()).ToList();
    

    针对下面的 M.kazem Akhgary 评论,如果您希望外部列表的排序不仅基于第一个元素而且还基于整个列表,我只能考虑这种解决方案。也许其他人有更好的解决方案。

    input.ForEach(t => t.Sort());
    input.Sort((e1, e2) => {
        for (int i = 0; i < e1.Count; i++)
        {
            if(e1[i] != e2[i])
            {
                return e1[i].CompareTo(e2[i]);
            }
        }
    
        return 0;
    });
    

    【讨论】:

    • 只是想知道,如果我 Sort() on input 会有什么影响。即input.Sort() ?
    • @Zeeshan : 如果你在 List 上不带任何参数直接调用 sort,它将尝试使用默认比较器来比较 List 和 List。但是默认没有,所以会有编译错误。为了在 List 上调用 Sort(),您需要告诉编译器如何比较 List 类型的 2 个元素,方法是为 Sort() 提供 lambda 表达式或自定义比较器
    • 如果第一个元素相等,那么第二个元素呢?
    • @M.kazemAkhgary 好点,我并没有真正考虑过。我用我想到的另一种解决方案修改了我的答案,如果有,请随时提出更好的解决方案
    • @M.kazemAkhgary 好点。我已经为此提出了一个答案。
    【解决方案2】:

    由于sortList 的签名具有返回类型,因此最好不要修改input 列表的内容——这可能会导致副作用和错误代码。

    我将如何解决这个问题:

    public static List<List<String>> sortList(List<List<String>> input)
    {
        return input
            .Select(x => x.OrderBy(y => y).ToList())
            .OrderBy(x => String.Join(", ", x))
            .ToList();
    }
    

    所以,给定这个输入:

    var input = new List<List<string>>()
    {
        new List<string>() { "fat", "twat", "gat", },
        new List<string>() { "cat", "hat", "bat", },
        new List<string>() { "twat", "lack", "rat", },
    };
    

    这将是输出:

    【讨论】:

    • 我认为使用 string.Join() 在 OrderBy() 中生成用于比较的键可能会导致不良影响。例如。比较“twat”和“twa”时,会将第一个元素的最后一个“t”与“,”字符进行比较
    • @PhuongNguyen - 有分隔符总比没有好。如果两个字符串分别是"ba", "ram""bar", "am" 会怎样?我认为从 OP 的示例中采用 ", " 分隔符是一个公平的选择,但它同样可以是 "|"
    • 您可以使用.OrderBy(x =&gt; String.Join(",", "["+x+"]"))进行排序,以消除"bar, "等包含元素的所有影响
    • @M.kazemAkhgary - 你指的是哪个黑客?
    【解决方案3】:

    我现在不确定如何对外面的列表进行排序。

    假设您已经对所有内部子列表进行了排序,现在您可以:

    input = input.OrderBy(subList => String.Join(",", subList)).ToList();
    

    这会将子列表连接到单个字符串以进行比较,这样如果第一个元素相同,它将比较列表的第二个元素。第三个,如果第二个元素相同...

    在使用String.Join()时应该有一个分隔符,以避免在比较第一个元素时意外使用第二个元素。分隔符不应出现在原始字符串中。

    【讨论】:

    • 这不会先排序内部列表。
    • @Enigmativity 我将编辑以澄清它,因为 OP 只要求对外部列表进行排序。
    • OP 要求根据 sorted 内部列表中的值对外部列表进行排序。
    【解决方案4】:

    您可以实现自己的列表比较器。不使用 Linq

    private static void Main()
    {
        List<List<string>> list = new List<List<string>>
        {
            new List<string> {"fat", "twat", "gat"},
            new List<string> {"cat", "hat", "bat"},
            new List<string> {"twat", "lack", "rat"}
        };
    
        // sort the inner list
        foreach (var l in list)
        {
            l.Sort();
        }
    
        list.Sort(new ListComparer<string>()); // sort outer list according to ListComparer class.
    }
    

    这是列表比较器。

    class ListComparer<T> : Comparer<List<T>> where T : IComparable
    {
        // Compare lists elements until they are no more equal.
        // return result of last compared elements as result.
        public override int Compare(List<T> x, List<T> y)
        {
            int compared = 0;
            for (int i = 0; compared == 0 && i < x.Count && i < y.Count ; i++)
            {
                compared = x[i].CompareTo(y[i]);
            }
            return compared;
        }
    }
    

    Compare 方法返回一个整数,指示第一个列表更大 (1) 还是第二个列表 (-1)。如果两个列表相等,它将返回0

    Sort 方法使用此结果来整理您的列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-06
      • 2017-10-28
      • 1970-01-01
      相关资源
      最近更新 更多