【问题标题】:Sort a list where each item refers to the items which should come before/after it对列表进行排序,其中每个项目指的是应该在它之前/之后的项目
【发布时间】:2015-03-27 17:08:48
【问题描述】:

我有一个未排序的对象列表。这些对象有:

  • PreviousId
  • 下一个ID

我想对列表进行排序,以便任何前面的项目的“NextId”都等于它后面的“PreviousId”。

例如

Item1:PreviousId = 15,NextId = 16

Item2:PreviousId = 16,NextId = 4

Item3:PreviousId = 4,NextId = 105

Item4:PreviousId = 105,NextId = 40

我能想到一些“杂乱无章”的方法,但是有没有标准的方法来做这样的事情?还是一种特别有效的方法?

【问题讨论】:

  • 你必须实现自定义逻辑来处理类似的事情。您必须确保每个前一个都有一个匹配的下一个。另外,你如何处理没有下一项或上一项的开始和结束?
  • 这似乎容易导致无法排序的可能性,例如孤儿或循环。

标签: c# list sorting


【解决方案1】:

如果 ID 是唯一的,您可以从列表中创建 Dictionary<PreviousId, object> 以轻松找到下一项。

【讨论】:

    【解决方案2】:

    请记住,为简洁起见,我将简化并省略某些方面以直接满足您的意图。

    我假设您已经准备好一些内容,但理论上您可以根据您的要求修改 Sort。您可以创建以下内容:

    private Enum Sortable { Previous, Next }
    private Enum Sorted { Ascending, Descending }
    

    这将为您的Sort 提供一个简洁明了的参数。现在我们假设你有一个模型来表示这个项目:

    protected void Sort<TKey>(ref List<Model> container, Sorted type, Sortable direction)
    {
         Comparison<Model> comparison = null;
         if(type == "Next")
              comparison = (i, j) => i.NextId.CompareTo(j.NextId);
         else { comparison = (i, j) => i.PreviousId.CompareTo(j.PreviousId);
    
         return comparison
    }
    

    这将是实现Sort 的一种方式。实现是原始的,加上我不担心AscendingDescending,所以你需要根据情况进行调整。但是,一旦实现了上述逻辑的核心,您只需调用:

    Sort<Model>(ref model, type, direction);
    
    • model 将代表您的 List&lt;Model&gt;
    • typedirection Enum 用于您的 Sort 标准。

    但是,上述实现的逻辑要广泛得多,如果您愿意,可以使用OrderByOrderByDescending 轻松完成。这可能会为您节省一些时间,因为您的实施更容易。

    【讨论】:

      【解决方案3】:

      对不起,我没有时间写代码,但我想一旦你找到了一个匹配的对,它们可以在列表中被某种聚合节点替换,因为这对现在将有一个“下一个”和一个“上一个”作为一个整体(第一个项目的前一个,第二个项目的下一个)。

      通过从主搜索中删除任何链接的项目,您将有更少的项目来搜索剩余的链接。 (请原谅错误的 ASCII 示例)

      2-3   8-9   1-2   5-6   7-8   4-5
      
      
      1-3         8-9  5-6   7-8   4-5
      (1-2, 2-3)
      
      1-5             8-9  5-6
      (1-2, 2-3, 4-5)
      

      您还可以通过检查每个项目的上一个或下一个来提高性能。 Prev 可以添加到开头,next 到结尾。

      【讨论】:

        【解决方案4】:

        我想出了这个解决方案。

                public class SampleObject
                {
                    public string Id { get; set; }
                    public string Next { get; set; }
                }
                public List<SampleObject> Sort(List<SampleObject> collection)
                {
                    var sortedCollection = new List<SampleObject>();
        
                    foreach (var item in collection)
                    {
                        var next = collection.FirstOrDefault(x => x.Id.Equals(item.Next));
        
                        if (next != null && !sortedCollection.Contains(next) && !sortedCollection.Contains(item))
                        {
                            sortedCollection.Add(item);
                            sortedCollection.Add(next);
                        }
                    }
        
                    return sortedCollection;
                }
        

        你可以这样使用它:

        var orderedCollection = Sort(yourUnorderedCollection);
        

        【讨论】:

          【解决方案5】:

          大多数“排序”算法不会按照您希望的方式工作,因为它们依赖于能够比较两个随机项目,并且比较需要是自反的(如果 a

          在您的情况下,仅遍历项目会更简单,可选择按照您想要的顺序将数据放入新集合中:

          Item current = list[0]; // or whatever starting point you need
          List<Item> sorted = new List<Item> {current};
          
          while(true)
          {
              Item next = list.SingleOrDefault(i => i.PreviousID == current.NextID);
              if(next == null) // no "next" found - exiting the loop
                  break;
          
              sorted.Add(next);  // add the "next" item to the list
              current = next;    // set the next" item to the "current" item
          }
          

          请注意,您可以对此进行很多改进:

          • 您可以将此逻辑放在 IEnumerator 函数中并使用 yield 语句,这样您就不会创建单独的结构
          • 您可以选择不同的“源”数据结构 (Dictionary&lt;int, Item&gt;?) 以加快查找速度

          【讨论】:

            猜你喜欢
            • 2021-05-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-12-29
            • 2022-07-23
            • 1970-01-01
            • 2011-04-09
            相关资源
            最近更新 更多