对列表进行排序,其中每个项目都指向应该在其之前/之后的项目

时间:2015-03-27 17:08:49

标签: c# list sorting

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

  • PreviousId
  • NextId

我想对列表进行排序,以便任何前面的项目都包含" NextId"等于" PreviousId"紧随其后。

E.g。

第1项:PreviousId = 15,NextId = 16

Item2:PreviousId = 16,NextId = 4

Item3:PreviousId = 4,Next Id = 105

Item4:PreviousId = 105,NextId = 40

我能想到一些"凌乱"方式,但有没有一种标准的方法来做这样的事情?还是一种特别有效的方式?

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

我假设你有一些内容,但理论上你可以根据你的要求修改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<Model>
  • typedirection Enum代表Sort的条件。

然而,所述实现的逻辑相当广泛,如果您愿意,可以轻松地使用OrderByOrderByDescending。这可能会为您节省一些时间,因为您的实施更容易。

答案 2 :(得分:1)

抱歉,我没有时间编写代码,但我想,一旦找到匹配的对,就可以通过某种聚合节点在列表中替换它们,因为它们现在有一个“next”和“previous”作为一个整体(第一个项目的前一个项目,第二个项目的下一个项目)。

通过从主搜索中删除任何链接的项目,您将有更少的项目来搜索剩余的链接。 (请原谅糟糕的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可以添加到开头,结尾。

答案 3 :(得分:1)

我已经提出了这个解决方案。

        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);

答案 4 :(得分:1)

大多数&#34;排序&#34; algorithims不会按照你想要的方式工作,因为它们依赖于能够比较两个随机项,并且比较需要是自反的(如果是&lt; b然后b&lt; a)和传递(如果&lt; b和b&lt; c然后a&lt; c)。

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

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语句,这样您就不会创建单独的结构
  • 您可以选择其他&#34;来源&#34;数据结构(Dictionary<int, Item>?)使查找更快