鉴于此:
['2014\\2014-01 Jan\\2014-01-01',
'2014\\2014-01 Jan\\2014-01-02',
'2014\\2014-01 Jan\\2014-01-03',
'2014\\2014-01 Jan\\2014-01-04',
'2014\\2014-01 Jan\\2014-01-05',
'2014\\2014-01 Jan\\2014-01-06',
'2014\\2014-01 Jan\\2014-01-07',
'2014\\2014-01 Jan\\2014-01-08',
'2014\\2014-01 Jan\\2014-01-09',
'2014\\2014-01 Jan\\2014-01-10',
'2014\\2014-01 Jan\\2014-01-11',
'2014\\2014-01 Jan\\2014-01-12',
'2014\\2014-01 Jan\\2014-01-13',
'2014\\2014-01 Jan\\2014-01-14',
'2014\\2014-01 Jan\\2014-01-15',
'2014\\2014-01 Jan\\2014-01-16',
'2014\\2014-01 Jan\\2014-01-17',
'2014\\2014-01 Jan\\2014-01-18',
'2014\\2014-01 Jan\\2014-01-19',
'2014\\2014-01 Jan\\2014-01-20',
'2014\\2014-01 Jan\\2014-01-21',
'2014\\2014-01 Jan\\2014-01-22',
'2014\\2014-01 Jan\\2014-01-23',
'2014\\2014-01 Jan\\2014-01-24',
'2014\\2014-01 Jan\\2014-01-25',
'2014\\2014-01 Jan\\2014-01-26',
'2014\\2014-01 Jan\\2014-01-27',
'2014\\2014-01 Jan\\2014-01-28',
'2014\\2014-01 Jan\\2014-01-29',
'2014\\2014-01 Jan\\2014-01-30',
'2014\\2014-01 Jan\\2014-01-31',
'2014\\2014-02 Feb\\2014-02-01',
'2014\\2014-02 Feb\\2014-02-02',
'2014\\2014-02 Feb\\2014-02-03',
'2014\\2014-02 Feb\\2014-02-04',
'2014\\2014-02 Feb\\2014-02-05',
'2014\\2014-02 Feb\\2014-02-06',
'2014\\2014-02 Feb\\2014-02-07',
'2014\\2014-02 Feb\\2014-02-08',
'2014\\2014-02 Feb\\2014-02-09',
'2014\\2014-02 Feb\\2014-02-10',
'2014\\2014-02 Feb\\2014-02-11',
'2014\\2014-02 Feb\\2014-02-12',
'2014\\2014-02 Feb\\2014-02-13',
'2014\\2014-02 Feb\\2014-02-14',
'2014\\2014-02 Feb\\2014-02-15',
'2014\\2014-02 Feb\\2014-02-16',
'2014\\2014-02 Feb\\2014-02-17',
'2014\\2014-02 Feb\\2014-02-18',
'2014\\2014-02 Feb\\2014-02-19']
你怎么得到这样的东西? (解决方案1:基于分隔符,具有用户可定义的分隔符)
['2014\\2014-01 Jan\\2014-01-01',
' \\2014-01-02',
' \\2014-01-03',
' \\2014-01-04',
' \\2014-01-05',
' \\2014-01-06',
' \\2014-01-07',
' \\2014-01-08',
' \\2014-01-09',
' \\2014-01-10',
' \\2014-01-11',
' \\2014-01-12',
' \\2014-01-13',
' \\2014-01-14',
' \\2014-01-15',
' \\2014-01-16',
' \\2014-01-17',
' \\2014-01-18',
' \\2014-01-19',
' \\2014-01-20',
' \\2014-01-21',
' \\2014-01-22',
' \\2014-01-23',
' \\2014-01-24',
' \\2014-01-25',
' \\2014-01-26',
' \\2014-01-27',
' \\2014-01-28',
' \\2014-01-29',
' \\2014-01-30',
' \\2014-01-31',
' \\2014-02 Feb\\2014-02-01',
' \\2014-02-02',
' \\2014-02-03',
' \\2014-02-04',
' \\2014-02-05',
' \\2014-02-06',
' \\2014-02-07',
' \\2014-02-08',
' \\2014-02-09',
' \\2014-02-10',
' \\2014-02-11',
' \\2014-02-12',
' \\2014-02-13',
' \\2014-02-14',
' \\2014-02-15',
' \\2014-02-16',
' \\2014-02-17',
' \\2014-02-18',
' \\2014-02-19']
我经常遇到这种情况,基本上我有一个字符串列表,我希望通过删除字符串开头的冗余匹配元素来更容易地进行处理。现在我知道这是普通文件夹遍历的TREE输出,但这些不是真正的文件夹,而只是列表中的字符串。
理想情况下,函数会接受一个层次分隔符,或者只是基于字符(seperator = None)。
def printheirarchy(data,seperator=","):
字符级层次结构的输出如下所示:(解决方案2:逐个字符)
['2014\\2014-01 Jan\\2014-01-01',
' 2',
' 3',
' 4',
' 5',
' 6',
' 7',
' 8',
' 9',
' 10',
' 1',
' 2',
' 3',
' 4',
' 5',
' 6',
' 7',
' 8',
' 9',
' 20',
' 1',
' 2',
' 3',
' 4',
' 5',
' 6',
' 7',
' 8',
' 9',
' 30',
' 1',
' 2 Feb\\2014-02-01',
' 2',
' 3',
' 4',
' 5',
' 6',
' 7',
' 8',
' 9',
' 10',
' 1',
' 2',
' 3',
' 4',
' 5',
' 6',
' 7',
' 8',
' 9']
这在这个例子中看起来不太有用,但在分析网址,日志等时非常明显。理想情况下,你只是将类似的部分变灰,而不是删除它们,但我甚至不知道如何开始。 (或相反,加粗差异)。基本上,您将每个元素与前一个元素进行比较,并突出显示差异和差异。抑制相似之处。
我已经搜索过并发现了许多与此相近的选项,但并非如此。 os.path.commonprefix
就是一个例子。也许difflib?
在检查项目列表时,值是减少视觉混乱。
答案 0 :(得分:3)
好像你想重新发明http://en.wikipedia.org/wiki/Radix_tree
无论如何,这是一个简单的发电机:
def grouped(iterable):
prefix = None
for i in iterable:
pre, suf = i[:16], i[16:]
if pre != prefix:
prefix = pre
yield pre + suf
else:
yield " " * 16 + suf
答案 1 :(得分:1)
好问题。这个小解决方案怎么样:
def commonPrefix(a, b):
i = 0
while i < len(a) and i < len(b) and a[i] == b[i]:
i += 1
return i
def eachWithPrefix(v):
p = ''
for x in v:
yield commonPrefix(p, x), x
p = x
现在你可以选择你想要的东西:
list(eachWithPrefix(v))
将返回一个值列表,每个值都会显示多少个字符等于前一行,所以
print '\n'.join(' '*p + x[p:] for p, x in eachWithPrefix(v))
将打印您提出的第二个解决方案。
print '\n'.join('\t' * p + '\\'.join(x[p:]) for p, x in eachWithPrefix(x.split('\\') for x in v))
另一方面,将对分隔符\
执行相同的操作,并使用制表位替换要省略的部分。这不是完全你在第一个输出示例中提出的格式,但我想你明白了。
尝试:
print '\n'.join('\\'.join([ s if i >= p else ' '*len(s) for i, s in enumerate(x) ]) for p, x in eachWithPrefix(x.split('\\') for x in v))
这将用相同大小的空间字符串替换相等的部分。但是输出仍然会包含分隔符,但可能更好:
2014\2014-01 Jan\2014-01-01
\ \2014-01-02
\ \2014-01-03
\ \2014-01-04
\ \2014-01-05
...
\ \2014-01-31
\2014-02 Feb\2014-02-01
\ \2014-02-02
\ \2014-02-03
...
要删除那些可以使用此方法的内容:
print '\n'.join(' ' * len('\\'.join(x[:p])) + '\\'.join(x)[len('\\'.join(x[:p])):] for p, x in eachWithPrefix(x.split('\\') for x in v))
但现在这包含一些代码翻倍,所以这里的迭代循环可能会更好:
for p, x in eachWithPrefix(x.split('\\') for x in v):
s = '\\'.join(x)
c = '\\'.join(x[:p])
print ' '*len(c) + s[len(c):]
或者作为易于使用的发电机:
def heirarchy(data, separator=","):
for p, x in eachWithPrefix(x.split(separator) if separator else list(x) for x in data):
s = separator.join(x)
c = separator.join(x[:p])
yield ' '*len(c) + s[len(c):]
所以现在heirarchy(data, separator='\\')
创建了您预期的输出。
答案 2 :(得分:1)
from difflib import SequenceMatcher
def remove_redundant_prefixes(it):
"""
remove_redundant_prefixes(it) -> iterable (generator)
Iterate through a list of strings, removing successive common prefixes.
"""
prev_line = ''
for line in sorted(it):
sm = SequenceMatcher(a=prev_line, b=line)
prev_line = line
# Returns 3 element tuple, last element is the size of the match.
match_size = sm.get_matching_blocks()[0][2]
# No match == no prefix, don't prune the string.
if match_size == 0:
yield line
else:
# Prune per the match
yield line.replace(line[:match_size], ' ' * match_size, 1)
答案 3 :(得分:0)
好的灵感来自this question的共同前缀答案我用它玩了一会儿,当我意识到我每次只发送一个只有两个元素的列表时就会有灵感!
这是我的代码,它只处理逐个字符的字符,我不确定这有多好(我怀疑不是很多!因为发生了很多不必要的复制)。但我能够成功地从我的问题中重现第三个输出。这仍然使另一部分得不到解决。
def printheirarchy(data,seperator=","):
if len(data) < 2:
pprint(data)
return
newdata = []
newdata.append(data[0])
for i in range(1,len(data)):
prefix = os.path.commonprefix(data[i-1:i+1])
newdata.append(data[i].replace(prefix," "*len(prefix),1))
pprint(newdata)