pythonic方法筛选具有唯一长度的元素的列表

时间:2015-05-26 22:07:56

标签: python filtering

我想过滤一个列表,只留下具有唯一长度的第一个元素。 我为它写了一个函数,但我相信应该有一个更简单的方法:

def uniq_len(_list):
    from itertools import groupby
    uniq_lens = list(set([x for x, g in groupby(_list, len)]))
    all_goods = []
    for elem in _list:
        elem_len = len(elem)
        try:
            good = uniq_lens.pop([i for i, x in enumerate(uniq_lens) if x==elem_len][0])
            if good:
                all_goods.append(elem)
        except IndexError as _e:
            #print all_goods
            pass
    return all_goods

In [97]: jones
Out[97]: ['bob', 'james', 'jim', 'jon', 'bill', 'susie', 'jamie']

In [98]: uniq_len(jones)
Out[98]: ['bob', 'james', 'bill']

5 个答案:

答案 0 :(得分:10)

如果你只想以任意顺序为每个长度任意字符串,那么最简单的方法是首先转换为dict将长度映射到字符串,然后只读取值:

>>> {len(s): s for s in jones}.values()
dict_values(['jon', 'bill', 'jamie'])

如果您想要每个长度的第一个,并且您需要保留订单,那么itertools recipes只有unique_everseen,而len>>> from more_itertools import unique_everseen >>> list(unique_everseen(lst, key=len)) ['bob', 'james', 'bill'] 关键:

itertools

(如果您pip install more-itertools,它包含var myName = "global"; 文档中的所有食谱,以及其他一些有用的内容。)

答案 1 :(得分:2)

获取具有唯一长度的列表的第一项(不一定与列表中显示的顺序相同)。

>>> lst = ['bob', 'james', 'jim', 'jon', 'bill', 'susie', 'jamie']
>>> list({len(x): x for x in reversed(lst)}.values())
['bob', 'bill', 'james']

尊重原始列表的顺序,您可以使用辅助集:

>>> seen = set()
>>> [x for x in lst if len(x) not in seen and seen.add(len(x)) is None]
['bob', 'james', 'bill']

要使上述表达式连续正常运行,您必须确保每次都将seen重置为空集。

答案 2 :(得分:1)

一种不太优雅的方式是:

>>> mylist = ['bob', 'james', 'jim', 'jon', 'bill', 'susie', 'jamie']
>>> filtered = []
>>> [filtered.append(x) for x in mylist if len(x) not in [len(y) for y in filtered]]
[None, None, None]
>>> print(filtered)
['bob', 'james', 'bill']

正如您所见,解释器打印[None, None, None],因为我们appendfiltered的行实际上生成了无值列表(append方法始终返回None ),然后丢弃。但该行的副作用是使用正确的值填充filtered

答案 3 :(得分:1)

简单的方法,只使用内置插件:

reduce(
         lambda o1, o2: o1 if o1 and len(o1[-1]) == len(o2) else o1 + [o2], 
         sorted(
                  orig, 
                  key=lambda o: len(o)
         ), 
         []
)

这会给你O(n * log(n))复杂性。

由于sorted是稳定的,等长字符串之间的顺序将与排序前的顺序相同。然后reduce函数将只留下每个长度的第一个匹配项。

答案 4 :(得分:-1)

列表推导是使代码更加pythonic的好方法。这里有一个很好的解释: List Comprehensions.

因此,如何执行上述操作的示例可能类似于:

from itertools import groupby

def filterUniqueLenghts(myList):
    lengths = {k:len(list(v)) for k,v in groupby(myList, lambda a: len(a))}
    return [e for e in myList if lengths[len(e)] == 1]

a = ['hello', 'hello', 'goodbye']
print(filterUniqueLenghts(a))

# prints ['goodbye']