在某些NLP任务中,我有一个嵌套的字符串列表:
[['Start', 'двигаться', 'другая', 'сторона', 'света', 'надолго', 'скоро'],
['Start', 'двигаться', 'другая', 'сторона', 'света', 'чтобы', 'посмотреть'],
['Start', 'двигаться', 'новая', 'планета'],
['Start', 'двигаться', 'сторона', 'признание', 'суверенитет', 'израильский'],
['Start', 'двигаться', 'сторона', 'признание', 'высот', 'на'],
['Start', 'двигаться', 'сторона', 'признание', 'высот', 'оккупировать'],
['Start', 'двигаться', 'сторона', 'признание', 'высот', 'Голанский'],
['Start', 'двигаться', 'сторона', 'признание', 'и']]
我需要一种算法来查找两个或更多元素,这些元素对于两个或更多子列表是常见的,并从中生成单个元素。在我的示例中,'Start', 'двигаться'
对于所有元素都是通用的,因此它应该成为单个字符串。 'сторона', 'света', 'надолго'
对于两个元素很常见,因此它成为单个字符串。 'сторона', 'признание'
对于5个元素很常见,因此它变成单个字符串。如果没有剩余公共元素,只需将其余元素添加为单个字符串。
期望的输出:
[['Start двигаться', 'другая сторона света', 'надолго скоро'],
['Start двигаться', 'другая сторона света', 'чтобы посмотреть'],
['Start двигаться', 'новая планета'],
['Start двигаться', 'сторона признание', 'суверенитет израильский'],
['Start двигаться', 'сторона признание', 'высот на'],
['Start двигаться', 'сторона признание', 'высот оккупировать'],
['Start двигаться', 'сторона признание', 'высот Голанский'],
['Start двигаться', 'сторона признание', 'и']]
到目前为止,我尝试了一些循环和元素比较:
for elem,next_elem in zip(lst, lst[1:]+[lst[0]]):
if elem[0] == next_elem[0] and elem[1] == next_elem[1] and elem[2] == next_elem[2]:
elem[0:3] = [' '.join(elem[0:3])]
if elem[0] == next_elem[0] and elem[1] == next_elem[1]:
elem[0:2] = [' '.join(elem[0:2])]
但我不认为这是正确的方法。集合也不是一个选项,因为子列表中可能会出现多个元素。 我检查了其他LCS主题,但没有找到解决方案。任何完成工作的工作算法都会很棒,效率目前并不重要。还有一些例子:
[[a,b,c,d],
[a,b,d,e,f]]
应该成为:
[[ab,cd],
[ab,def]]
由于a,b
是常见元素,cd, def
只是单个元素。
[[a,b,c,d,e,g],
[a,b,c,d,g,h],
[a,b,h,h,i]]
应该成为:
[[ab,cd,eg],
[ab,cd,gh],
[ab,hhi]]
由于ab
和cd
是两个或多个子列表的大炮
和
[[a,b,c],
[a,b,d]]
变为:
[[ab, c],
[ab, d]]
由于c, d
不是常见元素
答案 0 :(得分:1)
我建议你使用hashmaps键:word,value:整数作为计数器,从0开始。(这是python中的字典)。对于每一行,散列每个值并增加计数器。最后,对于每个具有2或更多计数器的单词,您将它们连接起来。
我遗漏了代码和你只用相同的计数器连接字符串的部分,以及重复,因为这似乎是家庭作业。
答案 1 :(得分:1)
您可以从创建代表您的列表的prefix-tree开始:
lists = [['Start', 'двигаться', 'другая', 'сторона', 'света', 'надолго', 'скоро'],
['Start', 'двигаться', 'другая', 'сторона', 'света', 'чтобы', 'посмотреть'],
['Start', 'двигаться', 'новая', 'планета'],
['Start', 'двигаться', 'сторона', 'признание'],
['Start', 'двигаться', 'сторона', 'признание', 'суверенитет', 'израильский'],
['Start', 'двигаться', 'сторона', 'признание', 'высот', 'на'],
['Start', 'двигаться', 'сторона', 'признание', 'высот', 'оккупировать'],
['Start', 'двигаться', 'сторона', 'признание', 'высот', 'Голанский'],
['Start', 'двигаться', 'сторона', 'признание', 'и']]
tree = {}
end = "END"
for lst in lists:
d = tree
for x in lst:
d = d.setdefault(x, {})
d[end] = {}
结果(此处,END
标记句子结束的位置):
{'Start': {'двигаться': {'другая': {'сторона': {'света': {'надолго': {'скоро': {'END': {}}},
'чтобы': {'посмотреть': {'END': {}}}}}},
'новая': {'планета': {'END': {}}},
'сторона': {'признание': {'END': {},
'высот': {'Голанский': {'END': {}},
'на': {'END': {}},
'оккупировать': {'END': {}}},
'и': {'END': {}},
'суверенитет': {'израильский': {'END': {}}}}}}}}
现在,您可以递归遍历该树,并且只要节点只有一个子节点(只有一个元素的子字典),就可以加入这些节点。
def join(d, pref=[]):
if end in d:
yield [' '.join(pref)] if pref else []
for k, v in d.items():
if len(v) == 1:
for x in join(v, pref + [k]): # add node to prefix
yield x # yield next segment
else:
for x in join(v, []): # reset prefix
yield [' '.join(pref + [k])] + x # yield node + prefix and next
输出不像你的问题那样完全,但非常接近。它将连接树中只有一个子节点的所有部分,即之后的段应该是最大的,而没有段是较长段的一部分。
>>> for x in join(tree):
... print(x)
...
['Start двигаться', 'другая сторона света', 'надолго скоро']
['Start двигаться', 'другая сторона света', 'чтобы посмотреть']
['Start двигаться', 'новая планета']
['Start двигаться', 'сторона признание']
['Start двигаться', 'сторона признание', 'суверенитет израильский']
['Start двигаться', 'сторона признание', 'высот', 'на']
['Start двигаться', 'сторона признание', 'высот', 'оккупировать']
['Start двигаться', 'сторона признание', 'высот', 'Голанский']
['Start двигаться', 'сторона признание', 'и']
以下是基于树的方法的说明。颜色表示没有任何分支的部分将被合并;端节点是粗体(那些不必是叶节点)。