根据 Python 中的键获取排序列表的一部分
Get a slice of a sorted list according to a key in Python
是否可以根据某个键值(例如列表项的长度)对排序列表进行切片?如果是,怎么做?
例如,我得到一个这样的排序列表:
sorted_list = sorted(some_list, key=len)
现在我想得到一个切片,其中包含具有最低和相等 len 的所有项目(即 len 的所有项目: min(sorted_list, key=len)
),它应该是排序列表的头部。
你可以这样做:
min_len = len(min(some_list, key=len))
sorted_list = sorted((x for x in some_list if len(x) == min_len), key=len)
它的作用是找到列表中最小元素的长度,然后在将列表传递给sorted
函数时过滤掉比该元素更长的元素。它需要额外传递数据以找到最小长度,但排序需要的时间比这长得多,因此时间成本实际上是无关紧要的。
您可以先对项目进行分组,然后获取第一个结果子迭代器的元素。
from itertools import groupby
firsts = list(next(groupby(sorted(some_list, key=len), len))[1])
例如,
>>> some_list = [[1, 2, 3], [4, 5, 6], [1], [2], [2, 3]]
>>> list(next(groupby(sorted(some_list, key=len), len))[1])
[[1], [2]]
此函数对列表进行排序,获取键(即最短长度的元素),然后构建一个仅包含等长元素的数组。
def slice_list(lst, func=len):
# start by sorting the list
sorted_lst = sorted(lst, key=func)
# get the key
key = func(sorted_lst[0])
# get the slice
slice = [v for v in sorted_lst if func(v) <= key]
return slice
由于没有测试用例,这里有一个(如果我正确解释了这个问题)
test = ['abcd', 'abcde', 'efgh', '1234', 'abcdef']
print(slice_list(test, len))
产出
['abcd', 'efgh', '1234']
这更多的是出于好奇而不是实用(因为 itertools 是 真正 性能)......你可以按最小值分组并避免在单次通过中排序,就像你可以在不排序的情况下找到列表的最小值。在这里,您只需跟踪当前最小值和所有相同大小的值。如果你发现一个较小的价值报废旧的并重新开始:
some_list = ['999', '11', '22', '343', '12', '545', '99', '11', '100', '11']
def minGroup(l, f):
it = iter(l)
current = [next(it)]
curr_min = f(current[0])
for item in it:
if f(item) < curr_min:
curr_min, current = f(item), [item]
elif f(item) == curr_min:
current.append(item)
return current
minGroup(some_list, len)
# ['11', '22', '12', '99', '11', '11']
minGroup(some_list, int)
# ['11', '11', '11']
是否可以根据某个键值(例如列表项的长度)对排序列表进行切片?如果是,怎么做?
例如,我得到一个这样的排序列表:
sorted_list = sorted(some_list, key=len)
现在我想得到一个切片,其中包含具有最低和相等 len 的所有项目(即 len 的所有项目: min(sorted_list, key=len)
),它应该是排序列表的头部。
你可以这样做:
min_len = len(min(some_list, key=len))
sorted_list = sorted((x for x in some_list if len(x) == min_len), key=len)
它的作用是找到列表中最小元素的长度,然后在将列表传递给sorted
函数时过滤掉比该元素更长的元素。它需要额外传递数据以找到最小长度,但排序需要的时间比这长得多,因此时间成本实际上是无关紧要的。
您可以先对项目进行分组,然后获取第一个结果子迭代器的元素。
from itertools import groupby
firsts = list(next(groupby(sorted(some_list, key=len), len))[1])
例如,
>>> some_list = [[1, 2, 3], [4, 5, 6], [1], [2], [2, 3]]
>>> list(next(groupby(sorted(some_list, key=len), len))[1])
[[1], [2]]
此函数对列表进行排序,获取键(即最短长度的元素),然后构建一个仅包含等长元素的数组。
def slice_list(lst, func=len):
# start by sorting the list
sorted_lst = sorted(lst, key=func)
# get the key
key = func(sorted_lst[0])
# get the slice
slice = [v for v in sorted_lst if func(v) <= key]
return slice
由于没有测试用例,这里有一个(如果我正确解释了这个问题)
test = ['abcd', 'abcde', 'efgh', '1234', 'abcdef']
print(slice_list(test, len))
产出
['abcd', 'efgh', '1234']
这更多的是出于好奇而不是实用(因为 itertools 是 真正 性能)......你可以按最小值分组并避免在单次通过中排序,就像你可以在不排序的情况下找到列表的最小值。在这里,您只需跟踪当前最小值和所有相同大小的值。如果你发现一个较小的价值报废旧的并重新开始:
some_list = ['999', '11', '22', '343', '12', '545', '99', '11', '100', '11']
def minGroup(l, f):
it = iter(l)
current = [next(it)]
curr_min = f(current[0])
for item in it:
if f(item) < curr_min:
curr_min, current = f(item), [item]
elif f(item) == curr_min:
current.append(item)
return current
minGroup(some_list, len)
# ['11', '22', '12', '99', '11', '11']
minGroup(some_list, int)
# ['11', '11', '11']