我有一个字典(多维?)像这样:
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?
如果你完全不关心键,并确保配对值将成为一个完整的圆圈。我想你可以试试这个:
通过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]]
希望对您有所帮助,并在您有其他问题时发表评论。 :)
像这样形成链的一组对具有这样的特性:每个元素在一对的第一个位置中恰好出现一次而在第二个位置中出现一次。如果您知道对中只有一个反转,则可以利用此属性:反向对中的第一个元素在第一个位置出现两次,第二个元素在第一个位置完全不出现。
这是一个想法:逐个检查对,并通过其第一个元素跟踪每对。当我们看到第二对具有相同的第一个元素时,这两个对中的一个必须是相反的 - 称为这些候选者。当我们看到其中一个候选者的第二个元素作为另一个候选者的第一个元素时,我们知道候选者不是反向候选者,所以我们反转另一个候选者。
该解决方案就地工作,这可能是也可能不是优势。转换为返回校正列表的那个很容易。它的优点还在于它只能通过一对列表 - 在最坏的情况下。在大多数情况下,它可以在结束前停止。在我的测试中,它比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