构建分层字符串

Build hierarchized strings

假设我有以下方法:

def _build_hierarchy(*keys):
     # ...

如果我调用 _build_hierarchy('a', 'b', 'c', 'd'),我希望得到以下 str 序列:

[
    'a',
    'a:b',
    'a:c',
    'a:d',
    'a:b:c',
    'a:b:d',
    'a:b:c:d'
]

请注意层次结构基于我提供参数的顺序。

老实说,我不知道该如何处理。

理想情况下,如果有的话,我想要一个非常简单的 pythonic 解决方案。

注意:解决方案需要兼容Python 2.7

你可以使用递归函数:

def _build_hierarchy(*keys):
  def combinations(d, current = []):
    if len(current) == len(keys):
      yield current
    else:
      if current:
        yield current
      for i in d:
        if (not current and keys[0] == i) or i not in current:
          if len(current)+1 < 3 or all(c ==d for c, d in zip(keys, current[:len(current)+1])):
            for c in combinations(d, current+[i]):
              yield c
  return sorted([i for i in combinations(keys) if i[0] == keys[0]], key=len)

print [':'.join(i) for i in _build_hierarchy('a', 'b', 'c', 'd')]

输出:

['a', 'a:b', 'a:c', 'a:d', 'a:b:c', 'a:b:d', 'a:b:c:d']

至于现在,尚不清楚根据哪个一般规则 a:c:d 没有出现在您的输出中。在添加精度之前,此答案假定它只是被遗忘了。

所需的输出接近于您输入的功率集。我们只要求第一个元素始终存在。因此,我们可以调整 powerset function from itertools recipes.

from itertools import chain, combinations

def _build_hierarchy (head, *tail, sep=':'):
     for el in chain.from_iterable(combinations(tail, r) for r in range(len(tail)+1)):
         yield sep.join((head,) + el)


for s in _build_hierarchy('a', 'b', 'c', 'd'):
    print (s)

输出

a
a:b
a:c
a:d
a:b:c
a:b:d
a:c:d
a:b:c:d

我认为是 "the first length-1 keys of item should be continuous, the last key can be isolated." 代码如下:

def _build_hierarchy(*keys):
    key_len = len(keys)
    result = []

    if key_len < 1:
        return result

    result.append(keys[0])
    for i in range(2, key_len + 1):
        #the first i-1 should be continuous, the last can be separate.
        pre_i = i - 1
        count = key_len - pre_i

        pre_str = ':'.join(keys[0:pre_i])
        for j in range(0, count):
            result.append(pre_str + ':' + keys[j + pre_i])

    return result


print _build_hierarchy()
print _build_hierarchy('a', 'b', 'c', 'd')