我正在复制Facebook的聊天阅读收据系统。我写了一些我觉得有用的基本代码。但是我的老板认为这会很慢。我没有算法训练。将索引映射返回到数字的最有效方法是什么,其中数字在排序列表中的两个数字之间,而索引是两个数字之间的第一个数字的索引?
# Given say {"a": 3, "b": 10, "c": 7, "d": 19} and [1,5,15] return {0: ["a"], 1: ["b", "c"], 2: ["d"]}
def find_read_to(read_dates, message_dates):
read_indexes_to_user_ids = {}
for user_id in read_dates:
for i, date in enumerate(message_dates):
last_index = i + 1 == len(message_dates)
next_index = -1 if last_index else i + 1
if last_index or (read_dates[user_id] >= date and read_dates[user_id] < message_dates[next_index]):
if i in read_indexes_to_user_ids:
read_indexes_to_user_ids[i].append(user_id)
else:
read_indexes_to_user_ids[i] = [user_id]
break
return read_indexes_to_user_ids
find_read_to({"a": 3, "b": 10, "c": 7, "d": 19}, [1,5,15])
使用bisect模块的版本
import bisect
def find_read_to(read_dates, message_dates):
read_indexes_to_user_ids = {}
user_ids, read_dates = zip(*read_dates.items())
def find_between(read_date):
answer = bisect.bisect_left(message_dates, read_date)
answer -= 1
if answer == -1:
return None
return answer
indexes_for_read_up_to = map(find_between, read_dates)
for i, index_for_read_up_to in enumerate(indexes_for_read_up_to):
user_id = user_ids[i]
if index_for_read_up_to is None:
continue
if index_for_read_up_to in read_indexes_to_user_ids:
read_indexes_to_user_ids[index_for_read_up_to].append(user_id)
else:
read_indexes_to_user_ids[index_for_read_up_to] = [user_id]
return read_indexes_to_user_ids
find_read_to({"a": 3, "b": 10, "c": 7, "d": 19}, [1,5,15])