【问题标题】:c# merge list but based on position relative to items in both listsc# 合并列表,但基于相对于两个列表中项目的位置
【发布时间】:2014-03-28 03:39:47
【问题描述】:

这不是典型的合并。我基本上有 2 个或更多需要合并的集合,并且项目的顺序很重要。集合的每个实例都将具有相同顺序的项目,但项目可能在也可能不在集合中。为了证明我将使用数字,但在实际应用中这些是对象。

collection_1 = [3,5,7,9]
collection_2 = [2,5,6]
collection_3 = [1,2,3,4,7,8]

After merge of collection 1 and 2 i am looking for
[3,2,5,6,7,9] or [2,3,5,7,9,6] or [3,2,5,7,9,6] are all correct
After merge above with collection 3
[1,2,3,4,5,6,7,8,9] (other variations possible)

我的想法是我会给它一堆集合以一个接一个地合并,但它不需要破坏任何集合的顺序。中间可以添加额外的物品,但顺序必须相同。

我知道这是一个奇怪的情况,但它是用于代码生成的,其中类上的属性的顺序必须是特定的顺序,因此它们会按照它们进入的顺序被序列化。如果一个属性不是填充然后它将不会被序列化,这就是为什么我可以在中间添加项目但不更改顺序的原因。为了以自动化的方式轻松比较输入和输出,我需要它们以相同的顺序出现,否则需要手动测试,我不想这样做:)

--- 编辑---

试着解释得更好一点。

我只能检查一个列表中的项目是否等于另一个列表中的项目。这些项目将是对象而不是上面的数字,并且无法按其内容进行排序。排序/排序基于项目相对于两个列表中项目的顺序。您可以做到这一点的唯一方法是知道一个列表是 100% 正确排序的,而第二个列表是合并的,因此可能会出现乱序。我的源列表将始终按相同的顺序排列,因此当由于较早的合并而发生冲突时,可以相信它们是事实点。

我也在研究一些可能的解决方案,但还没有运气

【问题讨论】:

  • 我很困惑,在合并集合 1 和 2 后,您如何在集合中包含 1
  • 很难理解您的要求。我看不出你如何确定在第一次合并中 3 必须在 2 之前出现任何逻辑,但在第二次合并中 2 在 3 之前是可以的。你需要给我们一个更好的解释。
  • @paqogomez 是的,这是一个错误,我已将其删除
  • @JimMischel 2 和 3 在第一次合并中可以是任何顺序。在第一次合并中,我将集合 2 合并到集合 1 中,因此如果订单中的任何订单部分不清楚,则使用已合并的集合。

标签: c# list merge


【解决方案1】:

如果我理解正确,您应该使用 HashSet 创建合并集合,然后使用排序。所以你必须创建自定义比较器。 您的要求难以理解,但如果合并数组的顺序基于合并前的顺序,您可能会使用包装器结构来存储合并前的项目位置。

【讨论】:

  • 那行不通。我只能检查平等。如果您想将它们视为字符串或单词并按顺序排序,发现不是按字母顺序排列的。我使用数字是因为它更容易,或者我认为它会。重要的是项目在列表中的顺序以及它们相对于两个列表中包含的项目的位置。
【解决方案2】:

在我设法想出以下方法来做到这一点之后。它并不完美,但似乎在 95% 的时间里都能让订单正确。下面是那些感兴趣的人的实现,如果有人有更好的实现,我仍然感兴趣。

public static List<T> OrderdMergeList<T>(this List<T> master, List<T> secondary)
    {
        var output = master.ToList();
        var itemsToInsert = new List<T>();
        int? lastMatchIndex = null;
        foreach (var item in secondary)
        {
            if (output.Contains(item))
            {
                if (!lastMatchIndex.HasValue)
                {
                    //already in the list so insert any items we have before this and not already in the output
                    var index = output.IndexOf(item);
                    output.InsertRange(index, itemsToInsert);
                    itemsToInsert.Clear();
                    lastMatchIndex = output.IndexOf(item);//updates it to new position
                }
                else
                {
                    //already in the list but also already found a match so need to be careful for out of order info
                    var index = output.IndexOf(item);
                    if (index > lastMatchIndex.Value)
                    {
                        output.InsertRange(index, itemsToInsert);
                        itemsToInsert.Clear();
                        lastMatchIndex = output.IndexOf(item); //updates it to new position
                    }
                    else
                    {
                        output.InsertRange(lastMatchIndex.Value+1, itemsToInsert);
                        if (itemsToInsert.Count > 0)
                        {
                            lastMatchIndex = output.IndexOf(itemsToInsert.Last()); //updates it to new position
                        }
                        else
                        {
                            lastMatchIndex += 1;
                        }
                        itemsToInsert.Clear();

                    }
                }
            }
            else
            {
                //not in the output so add it to the list to insert when we find a match
                itemsToInsert.Add(item);        
            }
        }
        //insert any left over items on the end
        output.AddRange(itemsToInsert);
        return output;
        //return master.Union(secondary).ToList();
    }

【讨论】:

    猜你喜欢
    • 2018-03-15
    • 2011-12-20
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-03-04
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    相关资源
    最近更新 更多