Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中2D列表的二进制搜索和返回列表_Python_Python 3.x_List_Multidimensional Array_Binary Search - Fatal编程技术网

Python中2D列表的二进制搜索和返回列表

Python中2D列表的二进制搜索和返回列表,python,python-3.x,list,multidimensional-array,binary-search,Python,Python 3.x,List,Multidimensional Array,Binary Search,我是Python编程新手,我已经尝试这个问题很长时间了,但是我没能想出一个解决方案。问题是我得到了一个员工ID列表和员工的出生年份,我应该返回一个在输入年份出生的员工ID列表。下面是列表的一个示例 lst=[[2,1987],[4,1990],[6,1992]…] 线性搜索需要太多时间,因为列表上有100万名员工。因此,我认为这个问题要求我们使用二进制搜索。我应该提出一个函数,该函数使用输入年份和lst生成一个返回员工ID的列表。如果该年没有出生的员工,则应返回空列表。下面是该函数的一个示例 输

我是Python编程新手,我已经尝试这个问题很长时间了,但是我没能想出一个解决方案。问题是我得到了一个员工ID列表和员工的出生年份,我应该返回一个在输入年份出生的员工ID列表。下面是列表的一个示例

lst=[[2,1987],[4,1990],[6,1992]…]

线性搜索需要太多时间,因为列表上有100万名员工。因此,我认为这个问题要求我们使用二进制搜索。我应该提出一个函数,该函数使用输入年份和lst生成一个返回员工ID的列表。如果该年没有出生的员工,则应返回空列表。下面是该函数的一个示例

输入>获取IDSU IDs2012

输出>[102204199632199649]


我知道有一个内置的对分函数,我可以对一维数组执行,但我不知道如何对二维数组执行二进制搜索。请建议我应该做什么,任何建议都非常感谢

首先,一百万个元素在现代硬件上并不多,所以使用筛选/列表可能会非常快。让我们先设置一些测试数据:

import random, bisect, operator
random.seed(0)

years = list(range(1950, 2003))
N = 1_000_000

employees = sorted([(i, random.choice(years)) for i in range(N)],
                  key=operator.itemgetter(1))

target_year = 1980
%timeit emp_1980 = [i for i, y in employees if y == target_year]
# 1 loop, best of 3: 261 ms per loop
# can query 4 years per second
您可以将内置的对分与列表而不是标量一起使用,但是默认情况下它会比较第一个元素ID,而不是我们想要的年份。我们可以通过一些预处理来解决这个问题:

import bisect
# all (year, id) pairs sorted by year
year_id_sorted = [[y, i] for i, y in sorted(employees, key=operator.itemgetter(1))]

def ids_from_year(target_y):
  result = list()
  # make use of elementwise list ordering
  i = bisect.bisect_left(year_id_sorted, [target_y, 0])
  for y, ID in year_id_sorted[i:]:
    if y == target_y:
      result.append(ID)
    else:
      break
  return result

%timeit ids_from_year(target_year)
# 100 loops, best of 3: 11.9 ms per loop
# can query 100 years per second
这将产生26倍的加速。还不算太糟,但我们已经产生了一些预处理成本,并且必须存储数据集的副本。现在,让我们尝试将员工存储在以下形式的字典中:year=>list of employees

from collections import defaultdict
employee_by_year = defaultdict(list)
for i, y in employees:
  employee_by_year[y].append(i)
# 1 loop, best of 3: 361 ms per loop
# pre-processing step is only %40 more expensive than
# a single lookup in the original case.

%timeit employee_by_year[target_year]
# 10000000 loops, best of 3: 63.2 ns per loop
# can query 16 million years per second
# other factors will likely limit processing speed

我认为最佳实现取决于您计划运行查询的频率。运行它至少两次可以证明使用dict是正确的。如果您使用的是粒度较小的度量,例如薪资,则可以证明使用二进制搜索是正确的。如果您需要查询多个指标,例如年薪,那么您会遇到内存与速度的权衡。那么,最佳策略实际上取决于您的数据分布。

要使二进制搜索起作用,您必须有一个排序列表。分类是有代价的;它表示一个Onlogn时间复杂性

但是,如果您使用按年份键入的字典,则无需二进制搜索即可完成此操作,且具有线性时间复杂度:

from collections import defaultdict 

# preprocessing
dic = defaultdict(list) # silently create an empty list when addressing a year the first time
for id, year in lst:
    dic[year].append(id)

# implementation of the required function 
def get_IDs(year):
    return dic[year]


您可以使用内置过滤器功能。