如何反转多维数组中的重复值

Posted

技术标签:

【中文标题】如何反转多维数组中的重复值【英文标题】:How to reverse duplicate value in multidimensional array 【发布时间】:2019-08-28 14:16:12 【问题描述】:

我有一本像这样的字典(多维?):

d =  0: [3, 5], 1: [5, 7], 2: [4, 7], 3: [4, 3] 

我想在字典列表中找到任何重复的匹配位置 (0) 或 (1) 值,如果存在重复,则反转第二个匹配的数字对。

字典会变成:

 0: [3, 5], 1: [5, 7], 2: [7, 4], 3: [4, 3] 

只有位置 (0) 是位置 (0) 的副本,并且只有位置 (1) 是位置 (1) 的副本,如果这有意义的话。一个系列中只能有一个重复,并且在重复数据删除/翻转过程之后,所有数字都应该链接在一起。下图说明:

[0 , 1] [1 , 2] [2 , 3] [3 , 0]

我正在尝试将所有相邻位置 (1) 与位置 (0) 匹配,因此这些值基本上是一个完整的圆圈(将其视为从一端连接到另一端的一系列线)。我愿意使用任何可能有助于有效解决此问题的 numpy 等。这是另一个例子:

 'foo': [2, 9], 'bar': [3, 2], 'baz': [3, 9]  

最终应该是什么:

[2, 9], [9, 3], [3, 2]

我尝试了很多类似的方法:

l = list(sorted(d.values()))

for i in range(0, len(l)):
    # now what the heck?

【问题讨论】:

结果应该是像您的第一个示例那样带有原始键的字典,还是像您的第二个示例那样是连接边的有序列表? @JohnZwinck:嗨,John,它应该是连接边的有序列表。字典索引真的没那么重要,因为我将根据边缘对最终结果进行排序。谢谢! 【参考方案1】:

像这样形成链的一组对具有以下特性:每个元素在一对的第一个位置只出现一次,在第二个位置出现一次。如果您知道您的配对中恰好有一个反转,您可以利用此属性:反转配对中的第一个元素在第一个位置出现两次,而第二个元素根本不出现在第一个位置。

这里的想法是:逐个检查对,并通过第一个元素跟踪每对。当我们看到第二对具有相同的第一个元素时,这两个对中的一个必须是相反的一对 - 称这些候选者。当我们看到其中一个候选的 second 元素作为另一对的第一个元素时,我们知道候选不是反转的,所以我们反转另一个。

此解决方案可就地运行,这可能是也可能不是优势。很容易转换为返回更正列表的列表。它还有一个优点,即它只遍历配对列表一次——在最坏的情况下。在大多数情况下,它可以在结束之前停止。在我的测试中,它比recnac 的解决方案快了大约七倍。

def fix_chain(pair_dict):
    first_to_pair = dict()
    this, that = None, None # candidates
    for pair in pair_dict.values():
        if pair[0] in first_to_pair: # found the collision
            this = pair
            that = first_to_pair[pair[0]]
        else:
            first_to_pair[pair[0]] = pair
        if this and this[1] in first_to_pair: # this is not reversed...
            that.reverse() # ... so that must be
            return
        if that and that[1] in first_to_pair: # that is not reversed...
            this.reverse() # ... so this must be
            return

【讨论】:

感谢您抽出宝贵时间回答我的问题。我回家后会测试它并报告结果。是什么让它比其他答案快七倍?我真的很好奇。 好问题!我没有描述其他答案。不过,我应该注意,我正在测试一万到数百万对的列表。对于 10000 对的列表,函数分别需要 1 毫秒和 7 毫秒。可能没有多大实际意义:)【参考方案2】:

如果您完全不关心键,并确保对值将形成一个完整的循环。我想你可以试试这个:

用dict存储每个数字的两个邻居(提高查询性能),从任意一个数字开始,然后遍历循环链,直到再次到达自己。

def reverse_pairs(input_dict):
    pair_values = list(input_dict.values())
    neighbors = defaultdict(list)

    for num1, num2 in pair_values:
        neighbors[num1].append(num2)
        neighbors[num2].append(num1)

    res = [pair_values[0]]
    while res[0][0] != res[-1][1]:
        a1, b1 = res[-1]
        a2, b2 = neighbors[b1]
        res.append([b1, a2 if a1 != a2 else b2])

    return res

测试用例:

def test():
    dict1 = 0: [3, 5], 1: [5, 7], 2: [7, 4], 3: [4, 3]
    print(reverse_pairs(dict1))

    dict2 = 'foo': [2, 9], 'bar': [3, 2], 'baz': [3, 9]
    print(reverse_pairs(dict2))

输出:

[[3, 5], [5, 7], [7, 4], [4, 3]]
[[2, 9], [9, 3], [3, 2]]

希望对您有所帮助,如果您还有其他问题,请发表评论。 :)

【讨论】:

以上是关于如何反转多维数组中的重复值的主要内容,如果未能解决你的问题,请参考以下文章

如何检查多维关联数组中的重复值?

如何从 PHP 中的多维数组中删除重复值 [重复]

有没有办法在java中的多维数组中反转特定数组?

如果两个值匹配,则从 php 中的多维关联数组中删除重复项

PHP按多维数组中的值排序[重复]

从php中的多维数组中删除重复值