基于索引更新 Python 列表的最快方法
Fastest way of updating a Python list based on indices
我有一个这样的 Python 字典 -
my_dict = {'Names':['Tom', 'Mariam', 'Lata', 'Tina', 'Abin'],
'Attendance':[False, False, False, False, False]}
我还有一个 Python 标志列表,其中的索引需要在 my_dict['Attendance']
-
中更改为 True
flag_list = [0, 2, 3]
在flag_list
的基础上,my_dict
需要改为-
my_dict = {'Names':['Tom', 'Mariam', 'Lata', 'Tina', 'Abin'],
'Attendance':[True, False, True, True, False]}
实现此目标最快的方法是什么?可以不用循环吗?感谢您的指导。
使用循环
for index in flag_list:
my_dict['Attendance'][index] = True
微优化是只从字典中获取列表一次:
attendance_list = my_dict['Attendance']
for index in flag_list:
attendance_list[index] = True
但除非 flag_list
是数千个元素,否则我不会担心它。
使用向量化
如果您愿意利用矢量化,您可以使用 numpy 数组:
import numpy as np
my_dict = {'Names':['Tom', 'Mariam', 'Lata', 'Tina', 'Abin'],
'Attendance': np.array([False, False, False, False, False])}
flag_list = [0, 2, 3]
my_dict['Attendance'][flag_list] = True
但同样,除非您的数据非常大,否则我不会非常担心优化这段代码。
示例计时
import random
from timeit import Timer
import numpy as np
ATTENDANCE_LIST_SIZE = 100000
FLAG_LIST_SIZE = 60000
dict_with_numpy = {'Attendance': np.random.choice([False, True],
ATTENDANCE_LIST_SIZE)}
dict_without_numpy = {'Attendance': random.choices([False, True],
k=ATTENDANCE_LIST_SIZE)}
flag_list = random.choices(range(ATTENDANCE_LIST_SIZE), k=FLAG_LIST_SIZE)
def using_numpy():
dict_with_numpy['Attendance'][flag_list] = True
def no_numpy_pre_fetching_list():
attendance_list = dict_without_numpy['Attendance']
for index in flag_list:
attendance_list[index] = True
def no_numpy():
for index in flag_list:
dict_without_numpy['Attendance'][index] = True
print(f'no_numpy\t\t\t\t\t\t{min(Timer(no_numpy).repeat(3, 3))}')
print(f'no_numpy_pre_fetching_list\t\t{min(Timer(no_numpy_pre_fetching_list).repeat(3, 3))}')
print(f'using_numpy\t\t\t\t\t\t{min(Timer(using_numpy).repeat(3, 3))}')
对于这个数据量,输出是(在我的机器上)
no_numpy 0.009737916999999985
no_numpy_pre_fetching_list 0.0048406370000000365
using_numpy 0.009164470000000036
因此对这些数据使用向量化是不是最有效的。
我有一个这样的 Python 字典 -
my_dict = {'Names':['Tom', 'Mariam', 'Lata', 'Tina', 'Abin'],
'Attendance':[False, False, False, False, False]}
我还有一个 Python 标志列表,其中的索引需要在 my_dict['Attendance']
-
flag_list = [0, 2, 3]
在flag_list
的基础上,my_dict
需要改为-
my_dict = {'Names':['Tom', 'Mariam', 'Lata', 'Tina', 'Abin'],
'Attendance':[True, False, True, True, False]}
实现此目标最快的方法是什么?可以不用循环吗?感谢您的指导。
使用循环
for index in flag_list:
my_dict['Attendance'][index] = True
微优化是只从字典中获取列表一次:
attendance_list = my_dict['Attendance']
for index in flag_list:
attendance_list[index] = True
但除非 flag_list
是数千个元素,否则我不会担心它。
使用向量化
如果您愿意利用矢量化,您可以使用 numpy 数组:
import numpy as np
my_dict = {'Names':['Tom', 'Mariam', 'Lata', 'Tina', 'Abin'],
'Attendance': np.array([False, False, False, False, False])}
flag_list = [0, 2, 3]
my_dict['Attendance'][flag_list] = True
但同样,除非您的数据非常大,否则我不会非常担心优化这段代码。
示例计时
import random
from timeit import Timer
import numpy as np
ATTENDANCE_LIST_SIZE = 100000
FLAG_LIST_SIZE = 60000
dict_with_numpy = {'Attendance': np.random.choice([False, True],
ATTENDANCE_LIST_SIZE)}
dict_without_numpy = {'Attendance': random.choices([False, True],
k=ATTENDANCE_LIST_SIZE)}
flag_list = random.choices(range(ATTENDANCE_LIST_SIZE), k=FLAG_LIST_SIZE)
def using_numpy():
dict_with_numpy['Attendance'][flag_list] = True
def no_numpy_pre_fetching_list():
attendance_list = dict_without_numpy['Attendance']
for index in flag_list:
attendance_list[index] = True
def no_numpy():
for index in flag_list:
dict_without_numpy['Attendance'][index] = True
print(f'no_numpy\t\t\t\t\t\t{min(Timer(no_numpy).repeat(3, 3))}')
print(f'no_numpy_pre_fetching_list\t\t{min(Timer(no_numpy_pre_fetching_list).repeat(3, 3))}')
print(f'using_numpy\t\t\t\t\t\t{min(Timer(using_numpy).repeat(3, 3))}')
对于这个数据量,输出是(在我的机器上)
no_numpy 0.009737916999999985
no_numpy_pre_fetching_list 0.0048406370000000365
using_numpy 0.009164470000000036
因此对这些数据使用向量化是不是最有效的。