我想过滤一个列表,只留下具有唯一长度的第一个元素。 我为它写了一个函数,但我相信应该有一个更简单的方法:
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']
答案 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]
,因为我们append
到filtered
的行实际上生成了无值列表(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']