【问题标题】:How to split a list based on the order of another list如何根据另一个列表的顺序拆分列表
【发布时间】:2018-09-01 14:15:51
【问题描述】:

假设我有一个任意列表[2, 5, 6, 2, 2, 4]

现在给定一个列表,我们称它为列表 A [1,2,3,4,5,6,0].List A 按特定顺序包含任意列表中的所有数字。现在让我们根据列表 A 的顺序排列第一个列表。每个新订单将成为一个新列表。所以结果应该是

[2,5,6]
[2]
[2,4]

另一个例子,如果列表是根据列表 B [4,5,6,0,1,2,3] 的顺序拆分的,那么结果应该是

[2]
[5,6,2]
[2]  
[4] <-- the different is that now the (ordered?) list change, the 4 is now belong on the next row.

我想以 LINQ 或函数式方式执行此操作。我在原始问题中发布了一个迭代解决方案,请在您回答或尝试回答此问题之前不要阅读它,因为我不想在答案中引入迭代偏见思维......

Split a list or ordered dates into weeks using linq

或者看下面的迭代答案

var orders = new List<int> { 4, 5, 6, 0, 1, 2, 3 };
var nums = new List<int> {2, 5, 6, 2, 2, 4};


        var queue = new Queue<int>(nums);
        var results = new List<List<int>>();
        while (queue.Count > 0)
        {
            var subLists = new List<int>();
            foreach (var order in orders)
            {
                if(order == queue.Peek())
                    subLists.Add(queue.Dequeue());


                if (queue.Count == 0)
                    break;
            }

            results.Add(subLists);
        }

【问题讨论】:

  • 为什么不使用实际的代码示例来输入?
  • 2 位于5listB 中的6 之后,为什么第二个示例中的第一个列表的第一项包含{2, 5, 6}?不应该是{2},然后是{5, 6}吗?
  • 请出示您的迭代解决方案代码
  • var 任意 = 新列表 { 1, 2, 3, 4, 5, 6, 0 }; var listA = new Queue(new List { 2, 5, 6, 2, 2, 4 }); var resultsA = new List>(); while (listA.Count > 0) resultsA.Add(arbitrary.Where(o => listA.Count != 0 && o == listA.Peek()).Select(o => listA.Dequeue()).ToList( )); // 你需要这样的东西吗?
  • 您得到的答案并不符合函数式编程的精神。这个问题没有意义;您声明列表 A 包含任意列表的编号,但在您的示例中并非如此。

标签: c# linq functional-programming


【解决方案1】:

非常简单,只需使用 for 循环:

            List<int> orderList = new List<int>(){ 1, 2, 3, 4, 5, 6, 0 };

            List<int> input = new List<int>(){ 2, 5, 6, 2, 2, 4 };

            List<List<int>> output = new List<List<int>>();
            List<int> temp = null;

            for (int i = 0; i < input.Count(); i++)
            {
                if (i == 0)
                {
                    temp = new List<int>();
                    output.Add(temp);
                    temp.Add(input[i]);
                }
                else
                {
                    if (orderList.IndexOf(input[i]) > orderList.IndexOf(input[i - 1]))
                    {
                        temp.Add(input[i]);
                    }
                    else
                    {
                        temp = new List<int>();
                        output.Add(temp);
                        temp.Add(input[i]);
                    }
                }
            }

【讨论】:

    【解决方案2】:

    我会通过遍历您想要一次拆分一个元素的列表来做到这一点。

    对于每个元素,在定义拆分顺序的列表中找到它的索引。将此与前一项的索引进行比较,如果更大,则将其添加到临时列表中。否则,将临时列表添加到结果列表并将临时列表设置为仅包含此项的新列表。

    继续以这种方式循环,直到得到 List&lt;List&lt;int&gt;&gt; 结果。

    代码可能更容易理解:

    public static List<List<int>> SplitOnList(List<int> toSplit, List<int> splitBy)
    {
        // Argument validation omitted (check for null and Lengths are equal)
    
        var results = new List<List<int>>();
        var singleResult = new List<int> {toSplit[0]};
    
        var lastIndex = splitBy.IndexOf(toSplit[0]);
    
        for (int i = 1; i < toSplit.Count; i++)
        {
            var thisItem = toSplit[i];
            var thisIndex = splitBy.IndexOf(thisItem);
    
            if (thisIndex > lastIndex)
            {
                singleResult.Add(thisItem);
            }
            else
            {
                results.Add(singleResult);
                singleResult = new List<int> { thisItem };
            }
    
            lastIndex = thisIndex;
        }
    
        results.Add(singleResult);
    
        return results;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-28
      • 1970-01-01
      • 2015-12-13
      • 2015-02-27
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 2020-01-14
      • 2021-05-23
      相关资源
      最近更新 更多