我有两个列表如下。
mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
Run Code Online (Sandbox Code Playgroud)
我想得到两个列表中公共元素的平均值,如下所示。
myoutput = [["chocolate", 0.5], ["egg", 0.45]]
Run Code Online (Sandbox Code Playgroud)
我目前的代码如下
for item1 in mylist1:
for item2 in mylist2:
if item1[0] == item2[0]:
print(np.mean([item1[1], item2[1]]))
Run Code Online (Sandbox Code Playgroud)
然而,由于有两个for
循环(O(n^2)
复杂性),这对于很长的列表来说效率很低。我想知道在 Python 中是否有更标准/更有效的方法来做到这一点。
Ada*_*Er8 38
您可以通过将 1 转换为 dict,然后在第二个列表中的每个项目访问该 dict(在 O(1) 中),在 O(n)(单次遍历每个列表)中完成它,如下所示:
mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
l1_as_dict = dict(mylist1)
myoutput = []
for item,price2 in mylist2:
if item in l1_as_dict:
price1 = l1_as_dict[item]
myoutput.append([item, (price1+price2)/2])
print(myoutput)
Run Code Online (Sandbox Code Playgroud)
输出:
[['chocolate', 0.5], ['egg', 0.45]]
Run Code Online (Sandbox Code Playgroud)
ACh*_*ion 17
O(n)
将平均所有项目的解决方案。
构造一个包含值列表的字典,然后平均该字典:
In []:
d = {}
for lst in (mylist1, mylist2):
for i, v in lst:
d.setdefault(i, []).append(v) # alternative use collections.defaultdict
[(k, sum(v)/len(v)) for k, v in d.items()]
Out[]:
[('lemon', 0.1), ('egg', 0.45), ('muffin', 0.3), ('chocolate', 0.5), ('milk', 0.2), ('carrot', 0.8)]
Run Code Online (Sandbox Code Playgroud)
然后,如果你只想要普通的,你可以添加一个守卫:
In []:
[(k, sum(v)/len(v)) for k, v in d.items() if len(v) > 1]
Out[]:
[('egg', 0.45), ('chocolate', 0.5)]
Run Code Online (Sandbox Code Playgroud)
这扩展到任意数量的列表,并且不对公共元素的数量进行假设。
这是一种用于collections.defaultdict
对项目进行分组并计算平均值的解决方案statistics.mean
:
from collections import defaultdict
from statistics import mean
mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
d = defaultdict(list)
for lst in (mylist1, mylist2):
for k, v in lst:
d[k].append(v)
result = [[k, mean(v)] for k, v in d.items()]
print(result)
# [['lemon', 0.1], ['egg', 0.45], ['muffin', 0.3], ['chocolate', 0.5], ['milk', 0.2], ['carrot', 0.8]]
Run Code Online (Sandbox Code Playgroud)
如果我们只想要公共键,只需检查值是否大于 1:
result = [[k, mean(v)] for k, v in d.items() if len(v) > 1]
print(result)
# [['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)
我们也可以从集合交集构建结果:
mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
d1, d2 = dict(mylist1), dict(mylist2)
result = [[k, (d1[k] + d2[k]) / 2] for k in d1.keys() & d2.keys()]
print(result)
# [['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)
您可以使用Pandas库来避免自己编写任何类型的循环。
您的代码将非常简洁和干净。
像安装熊猫:pip install pandas
。
然后试试这个:
In [132]: import pandas as pd
In [109]: df1 = pd.DataFrame(mylist1)
In [110]: df2 = pd.DataFrame(mylist2)
In [117]: res = pd.merge(df1, df2, on=0)
In [121]: res['mean'] = res.mean(axis=1)
In [125]: res.drop(['1_x', '1_y'], 1, inplace=True)
In [131]: res.values.tolist()
Out[131]: [['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)
编辑
Pandas 非常快,因为它numpy
在幕后使用。Numpy 实现了高效的数组操作。
请查看帖子:为什么 Pandas 的速度如此之快?有关mean
通过计算的更多详细信息pure Python vs Pandas
。
为了轻松操纵您的值,我建议使用 a dict
,找到公共键并计算平均值:
mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
recipe_1 = dict(mylist1) # {'lemon': 0.1, 'egg': 0.1, 'muffin': 0.3, 'chocolate': 0.5}
recipe_2 = dict(mylist2) # {'chocolate': 0.5, 'milk': 0.2, 'carrot': 0.8, 'egg': 0.8}
common_keys = recipe_1.keys() & recipe_2.keys() # {'chocolate', 'egg'}
myoutput = [[item, np.mean((recipe_1[item], recipe_2[item]))] for item in common_keys]
myoutput = [[item, (recipe_1[item] + recipe_2[item]) / 2] for item in common_keys]
Run Code Online (Sandbox Code Playgroud)
将列表转换为字典
d_list1 = dict(mylist1)
d_list2 = dict(mylist2)
[[k, (v+d_list2[k])/2] for k, v in d_list1.items() if k in d_list2]
#[['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)
您可以使用set
intersection
方法从两个列表中获取公共键,然后使用列表推导计算平均值:
mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
dict1 = dict(mylist1)
dict2 = dict(mylist2)
res = [[key, (dict1.get(key)+dict2.get(key))/2] for key in set(dict1.keys()).intersection(set(dict2.keys()))]
print(res)
Run Code Online (Sandbox Code Playgroud)
输出:
>> [['chocolate', 0.5], ['egg', 0.45]]
Run Code Online (Sandbox Code Playgroud)
您可以在交换集合交集所需的时间内完成,这显然是 O(min(N1,N2)) 其中 N1, N2 是列表长度。
intersect = set([a[0] for a in mylist1]).intersection([a[0] for a in mylist2])
d1=dict(mylist1)
d2=dict(mylist2)
{i:(d1[i]+d2[i])/2 for i in intersect}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2283 次 |
最近记录: |