繁体   English   中英

将具有共同元素的所有子阵列合并为一个子阵列

[英]Merging all sub-arrays with mutual elements into one sub-array

我需要找到共享任何相互元素的所有子数组,并将它们合并为一个子数组。 (在Python中实现,但是任何算法思想都将有所帮助)

多维数组结构:

categories = {'car':['automobile','auto'],
             'bike':['vehicle','motorcycle','motorbike','automobile'],
             'software':['computer','macbook','apple','microsoft','mozilla'],
             'firefox':['internet','mozilla','browser']
             'bicycle':['vehicle']}

我想将“汽车”,“自行车”和“自行车”合并到一个列表中( 保留第一个列表的密钥, 新列表的密钥可以是任何相关密钥),并且将“软件”和“ firefox”合并为一个列表,如下所示:好。

性能至关重要。

我能来与迄今最好的办法是保持平坦元件 => list_key(例如“ 汽车 ” =>“ 汽车 ”)的一维数组,然后运行下面的递归函数的多维阵列中的每个列表(伪代码) :

function merge_similar(list_key):
    For each element in categories[list_key]:
        If flatten_array.has_key(element):
            list_to_merge = flatten_array[element]
            merge_similar(list_to_merge) /* merge other lists which share an element with our newly found similar list */
            categories[list_key] = merge(categories [list_key], categories[list_to_merge])
            delete categories[list_to_merge]

知道如何改善其性能吗?

谢谢!

请注意, 没有 “第一个关键” -类型的字典不守秩序,所以如果你需要一些为了保持住,你就需要一些不同的,额外的数据结构开始。

除了与订单相关的问题外,我将从类似的内容开始:

def merged(dictoflists):
  result = dict()
  reversed = dict()
  for k, l in dictoflists.iteritems():
    intersecting = set(reversed.get(w) for w in l) - set([None])
    if intersecting:
      pickone = intersecting.pop()
      into = result[pickone]
    else:
      pickone = k
      into = result[k] = set()
    for ok in intersecting:
      into.update(result.pop(ok))
    into.update(l)
    for w in into:
      reversed[w] = pickone
  return dict((k, sorted(l)) for k, l in result.iteritems())

如果顺序对您很重要,则使用set将会有问题,并且您将需要更复杂(且速度更慢)的数据结构-但是,在这种情况下,您应该首先完整详细地说明您需要精确的顺序约束尊重可能发生的各种可能情况。

我无法想象递归解决方案会很快。
使用list.extend()是否太慢?
您可以执行以下操作:

categories['car'].extend(categories['bike']);
categories['car'].extend(categories['bicycle']);

或更笼统地说,如果您传递要合并的键列表:

first_key=None;
for key in keys_whose_lists_I_want_to_merge:
    if first_key is None:
        first_key=key;
    else:
        categories[first_key].extend(categories[key]);

如果要合并大量列表,则可以优化该循环,使其在第一次之后不执行“无”检查。 请参阅“ Python性能提示”页面上的标题为“在运行时重新映射函数”的提示

>>> categories = {'car':['automobile','auto'],
             'bike':['vehicle','motorcycle','motorbike','automobile'],
             'software':['computer','macbook','apple','microsoft','mozilla'],
             'firefox':['internet','mozilla','browser'],
             'bicycle':['vehicle']}
>>> # Use sets for values
>>> for k,v in categories.items(): categories[k] = set(v)

>>> # Acumulate
>>> for k1, v1 in categories.items():
    if v1:
        for k2,v2 in categories.items():
            if v2 and k1 != k2 and v1 & v2:
                v1 |= v2
                categories[k2] = None
        categories[k1] = v1


>>> # Print
>>> for k1, v1 in categories.items():
    if v1: print('%s: %r' %(k1,v1))


bicycle: {'motorbike', 'vehicle', 'auto', 'automobile', 'motorcycle'}
firefox: {'apple', 'mozilla', 'macbook', 'computer', 'internet', 'microsoft', 'browser'}
>>> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM