来自列表理解的字典
Dictionary from list comprehension
我有以下列表。
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
我找到了字典键,这是元组中的第一项。
keys = {i[0] for i in arr_lst}
# output
# {1, 2, 3)
从那里,我创建了一个字典,如果元组中的第一项与之前定义的键匹配,则其值为第一个列表中的元组。
id_dict = dict()
for k in keys:
id_dict[k] = [i for i in arr_lst if i[0] == k]
# output
# {1: [(1, 34, 99)], 2: [(2, 35, 40), (2, 36, 50), (2, 37, 10)], 3: [(3, 37, 90), (3, 38, 8)]}
然后我创建了一个新列表,其元素是基于字典值的元组。第三项在字典值中最高的元组被附加到列表中,第三项被删除。
output_id_etak_id = []
for k, v in id_dict.items():
m = max(v, key=lambda x: x[2])
output_id_etak_id.append(m[:2])
# output
# [(1, 34), (2, 36), (3, 37)]
代码有效,我得到了想要的输出。但是,我有一个大型数据集,第一个列表中有超过 800 000 个元素,目前需要大约 3 个小时才能 运行。我想找到一种让它更快的方法。
你可以itertools.groupby
(expects sorted input) to form groups based on the tuple 1st element and then select the first element of that group using next
(suggested by @tobias-k).
注:为了使用next
我们需要使用比较键[=22=对列表进行排序]x[0],-x[-1] 这样组成的组按降序排列.
from itertools import groupby
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_lst = sorted(arr_lst, key=lambda x: <b>(x[0], -x[-1])</b>)
result = [
<b>next(group)</b>[:2]
for key, group in groupby(arr_lst, key=lambda x: x[0])
]
键=第一个元素;值 = 第三个元素的最大值的第二个元素
如果你想要第三个元素有最大值的第二个元素,那么你可以使用这个代码:
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_dict = {}
arr_temp = {}
for arr in arr_lst:
x = arr_temp.get(arr[0],-1)
if arr[2] > x:
arr_temp[arr[0]] = arr[2]
arr_dict[arr[0]] = arr[1]
arr_relist = [(k,v) for k,v in arr_dict.items()]
print (arr_relist)
这个输出将是:
[(1, 34), (2, 36), (3, 37)]
时间安排是:
For dictionary:
841 ns ± 21.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Including recreating the list with tuples:
1.18 µs ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
键=第一个元素;值 = 第三个元素的最大值
根据评论部分,我假设您希望元组中的第一项作为键,元组中第三项的最大值作为键的值。
为此,您只需迭代一次循环。
您的代码将是:
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_dict = {}
for arr in arr_lst:
x = arr_dict.get(arr[0],-1)
if arr[2] > x: arr_dict[arr[0]] = arr[2]
print (arr_dict)
这个输出将是:
{1: 99, 2: 50, 3: 90}
我检查了这个时间:
792 ns ± 15.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
您可以使用itertools.groupby and map来完成这个任务
import itertools
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
def max_2_1(arr):
maxItem = next(arr)
for item in arr:
if item[2] > maxItem[2]:
maxItem = item
return maxItem[1]
arr_lst.sort(key = lambda kk: kk[0]) # important as groupby rely on this
aa = map(
lambda keygroup: [ keygroup[0], max_2_1( keygroup[1] ) ],
itertools.groupby(arr_lst, key=lambda item: item[0])
)
print(list(aa)) # [[1, 34], [2, 36], [3, 37]]
我有以下列表。
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
我找到了字典键,这是元组中的第一项。
keys = {i[0] for i in arr_lst}
# output
# {1, 2, 3)
从那里,我创建了一个字典,如果元组中的第一项与之前定义的键匹配,则其值为第一个列表中的元组。
id_dict = dict()
for k in keys:
id_dict[k] = [i for i in arr_lst if i[0] == k]
# output
# {1: [(1, 34, 99)], 2: [(2, 35, 40), (2, 36, 50), (2, 37, 10)], 3: [(3, 37, 90), (3, 38, 8)]}
然后我创建了一个新列表,其元素是基于字典值的元组。第三项在字典值中最高的元组被附加到列表中,第三项被删除。
output_id_etak_id = []
for k, v in id_dict.items():
m = max(v, key=lambda x: x[2])
output_id_etak_id.append(m[:2])
# output
# [(1, 34), (2, 36), (3, 37)]
代码有效,我得到了想要的输出。但是,我有一个大型数据集,第一个列表中有超过 800 000 个元素,目前需要大约 3 个小时才能 运行。我想找到一种让它更快的方法。
你可以itertools.groupby
(expects sorted input) to form groups based on the tuple 1st element and then select the first element of that group using next
(suggested by @tobias-k).
注:为了使用next
我们需要使用比较键[=22=对列表进行排序]x[0],-x[-1] 这样组成的组按降序排列.
from itertools import groupby
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_lst = sorted(arr_lst, key=lambda x: <b>(x[0], -x[-1])</b>)
result = [
<b>next(group)</b>[:2]
for key, group in groupby(arr_lst, key=lambda x: x[0])
]
键=第一个元素;值 = 第三个元素的最大值的第二个元素
如果你想要第三个元素有最大值的第二个元素,那么你可以使用这个代码:
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_dict = {}
arr_temp = {}
for arr in arr_lst:
x = arr_temp.get(arr[0],-1)
if arr[2] > x:
arr_temp[arr[0]] = arr[2]
arr_dict[arr[0]] = arr[1]
arr_relist = [(k,v) for k,v in arr_dict.items()]
print (arr_relist)
这个输出将是:
[(1, 34), (2, 36), (3, 37)]
时间安排是:
For dictionary:
841 ns ± 21.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Including recreating the list with tuples:
1.18 µs ± 41.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
键=第一个元素;值 = 第三个元素的最大值
根据评论部分,我假设您希望元组中的第一项作为键,元组中第三项的最大值作为键的值。
为此,您只需迭代一次循环。
您的代码将是:
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
arr_dict = {}
for arr in arr_lst:
x = arr_dict.get(arr[0],-1)
if arr[2] > x: arr_dict[arr[0]] = arr[2]
print (arr_dict)
这个输出将是:
{1: 99, 2: 50, 3: 90}
我检查了这个时间:
792 ns ± 15.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
您可以使用itertools.groupby and map来完成这个任务
import itertools
arr_lst = [(1, 34, 99), (2, 35, 40), (2, 36, 50), (2, 37, 10), (3, 37, 90), (3, 38, 8)]
def max_2_1(arr):
maxItem = next(arr)
for item in arr:
if item[2] > maxItem[2]:
maxItem = item
return maxItem[1]
arr_lst.sort(key = lambda kk: kk[0]) # important as groupby rely on this
aa = map(
lambda keygroup: [ keygroup[0], max_2_1( keygroup[1] ) ],
itertools.groupby(arr_lst, key=lambda item: item[0])
)
print(list(aa)) # [[1, 34], [2, 36], [3, 37]]