【问题标题】:Merging all sub-arrays with mutual elements into one sub-array将所有具有相互元素的子数组合并为一个子数组
【发布时间】:2011-01-07 02:57:23
【问题描述】:

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

多维数组结构:

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

我想将“汽车”、“自行车”和“自行车”合并到一个列表中(保留第一个列表的键新列表的键可以是任何相关键)和“软件” ' 和 'firefox' 也合并到一个列表中。

性能至关重要。

到目前为止,我能想到的最佳解决方案是保持 element => list_key 的扁平一维数组(例如,'automobile ' => 'car') 然后对多维数组中的每个列表运行以下递归函数(伪代码):

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]

知道如何提高它的性能吗?

谢谢!

【问题讨论】:

  • 不确定“保留第一个列表的键”是否有意义,因为它们是字典键,因此是无序的。 “第一”在该语句中没有任何意义。
  • 新列表的键实际上并不重要 - 已修复。谢谢

标签: python performance algorithm arrays


【解决方案1】:

请注意,没有“第一个键”——dicts 不保持顺序,因此如果您需要保留一些顺序,则需要从一些不同的替代数据结构开始。

除了与订单相关的问题,我会从以下内容开始:

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 的使用会出现问题,您将需要更复杂(且速度更慢)的数据结构——但是,如果是这种情况,您应该首先详细说明在可能发生的各种情况下,您需要遵守的排序约束。

【讨论】:

  • 看起来不错,打算再做一些测试。关键实际上并不重要 - 我已经修复了我的帖子。谢谢!
【解决方案2】:

我无法想象递归解决方案会很快。
使用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 Performance Tips 页面上题为“在运行时重新映射函数”的提示。

【讨论】:

    【解决方案3】:
    >>> 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'}
    >>> 
    

    【讨论】:

      猜你喜欢
      • 2015-02-02
      • 2020-04-07
      • 1970-01-01
      • 2021-12-16
      • 2012-03-04
      • 1970-01-01
      • 2015-05-19
      • 1970-01-01
      相关资源
      最近更新 更多