识别列表中字符串中出现的元素

时间:2014-04-04 17:23:54

标签: python

我们说我有一个列表,管道表示层次结构。

l = ['animals|fish|salmon', 'fish|salmon', 'fish', 'animals', 'furniture',
    'animals|big cats|lions', 'animals|birds|fisher bird']

我想返回一个包含所有非冗余条目的列表:

l = ['animals|fish|salmon', 'animals|big cats|lions',
     'animals|birds|fisher bird', 'furniture']

我尝试了按长度排序列表的各种变体,然后使用" any"用于查找其中一个条目中包含的元素的关键字。

l2 = paths.sort(key=len)
for i in l2:
    if any(i in j for j in l if i != j):
...

但这并不是真的很成功。任何人都可以推荐更好的方法来解决这个问题吗?

谢谢!

4 个答案:

答案 0 :(得分:3)

我不确定这是否是您要找的:

l = ['animals|fish|salmon', 'fish|salmon', 'fish', 'animals', 'furniture',
    'animals|big cats|lions', 'animals|birds|fisher bird']

def simplify (data):
    data = ['|{}|'.format (e) for e in data]
    return [e [1:-1] for e in data if all (e is other or e not in other for other in data) ]

print (simplify (l) )

打印:

['animals|fish|salmon', 'furniture', 'animals|big cats|lions', 'animals|birds|fisher bird']

我的所作所为:

第一步:将管道放在每个项目的开头和结尾'|{}|'.format(以避免与例如fishfisher bird发生冲突。

第二步:过滤列表,丢弃除自己(e not in other)之外的另一个(e is other or)子路径的所有项目。我还修剪了额外的管道(e [1:-1]

答案 1 :(得分:2)

你可以这样做。

我在这里使用set来跟踪已经看过的项目。我循环遍历每个项目,首先在空格分割,然后在|分割,下一步是检查该列表中的任何项目是否在seen集合中不存在,如果是,则将该字符串存储在out列表中,并将列表中的项添加到seen集。

lis = ['animals|fish|salmon', 'fish|salmon', 'fish', 'animals', 'furniture',
    'animals|big cats|lions', 'animals|birds|fisher bird']
seen = set()
out = []
for x in lis:
    items = [z for y in x.split() for z in y.split('|')]
    if any(y not in seen for y in items):
        seen.update(items)
        out.append(x)
print out        

#['animals|fish|salmon', 'furniture', 'animals|big cats|lions', 'animals|birds|fisher bird']        

答案 2 :(得分:1)

早些时候我问过"如果你说l = ['animals|fish', 'fish|salmon']会怎么样?"而且我感到无聊所以我已经摆弄了一个解决方案来完全返回所有独特的链条。

现在['animals|fish', 'fish|salmon'] -> ['animals|fish|salmon']

['animals|fish|trout', 'fish|salmon'] -> ['animals|fish|salmon','animals|fish|trout']

您可以为每个物种创建一个节点,其中包含一个子物种及其亲本物种的列表。对于列表中的每只动物个体动物,您可以创建一个节点。对于列表中的每个字符串,您将子动物链接到它前面的父动物。

当您完成后,您将打印所有没有父母的动物的等级。

class SpeciesNode(object):
    def __init__(self, name):
        self.parent = None
        self.name = name
        self.children = []
    def add_node(self,s_node):
        if not s_node in self.children:
            s_node.parent = self
            self.children.append(s_node)
    def get_branches(self):
        if len(self.children) == 0:
            yield self.name
        else:
            for child in self.children:
                for branch in child.get_branches():
                    yield self.name + '|' + branch

现在,您可以定义一个函数,将层次结构列表转换为节点列表。

def get_s_nodes(animal_list):
    s_nodes = {}
    for hierarchy in animal_list:
        h_list = hierarchy.split('|')
        parent = None
        for species in h_list:
            if not species in s_nodes.keys():
                s_nodes[species] = SpeciesNode(species)
            if parent is not None:
                s_nodes[parent].add_node(s_nodes[species])
            parent = species
    return s_nodes.values()

最后将其转换回字符串列表

def get_animal_list(s_nodes):
    animal_kingdom = []
    for node in s_nodes:
        if node.parent is None:
            for branch in child.get_branches():
                animal_kingdom.append(branch)
    return animal_kingdom

这样:

>>> l = ['animals|fish|salmon', 'fish|salmon','fish|trout', 'salmon|salmon eggs', 'fish', 'animals',
         'furniture', 'animals|big cats|lions', 'animals|birds|fisher bird']
>>> get_animal_list(get_s_nodes(l))
['animals|fish|salmon|salmon eggs', 'animals|fish|trout', 'animals|big cats|lions', 'animals|birds|fisher bird', 'furniture']
>>> 

答案 3 :(得分:0)

我认为"冗余"的定义这里没有100%明确。你的帖子似乎表明,如果一个条目中的所有文字都出现在另一个条目中,那么这个文章是多余的,但我不认为这真的是你的意思。例如,即使['fish', 'fishers']['fishers']也可能不应简化为'fish' in 'fishers' == True

我猜你想要的更接近这个:

def is_redundant(a, b):
   """Is a redundant given b?"""
   a_parts = set(a.split('|'))
   b_parts = set(b.split('|'))
   return len(a_parts.intersect(b_parts) == len(b_parts)

这是一个简单(但效率低下)的解决方案:

for item in l:
    l = filter(lambda x: not is_redundant(x, item), l)