我有一个包含比率值的OrderedDictionary。每个条目都有一个密钥的日期(每个日期恰好是一个年度季度的开始),并且值是一个数字。日期按从最早到最新的顺序插入。
{
date(2017, 1, 1): 95,
date(2018, 1, 1): 100,
date(2018, 6, 1): 110,
date(2018, 9, 1): 112,
}
我的利率词典比这大得多,但这是总的想法。给定一个任意日期,我想在之前的字典中找到该值。例如,查找日期date(2018, 8, 1)
应该返回值110,因为条目date(2018, 6, 1)
是我查找日期之前的最近键。同样,日期date(2017, 12, 1)
应该返回95,因为最接近的前一个键恰好是date(2017, 1, 1)
。
我可以通过浏览字典中的项目轻松地做到这一点:
def find_nearest(lookup):
nearest = None
for d, value in rates.items():
if(d > lookup):
break
nearest = value
return nearest
这对我来说感觉效率低下,因为在最坏的情况下,我必须扫描整个字典(我之前提到的字典可能很大)。我将进行成千上万的此类查找,因此我希望它表现出色。
解决性能问题的另一种方法是创建一个我所看到的缓存,这也是可行的,尽管我想知道内存限制(我不完全确定缓存会增长多大)。
在这里可以使用任何聪明的方法或Python核心模块吗?
答案 0 :(得分:2)
由于您要按顺序在dict中插入日期,并且大概使用的是Python 3.7(这使dict的顺序有意义),因此您可以使用递归函数来划分和征服以在O中找到键列表的所需索引(log n)时间复杂度:
def find_nearest(l, lookup):
if len(l) == 1:
return l[0]
mid = len(l) // 2
if l[mid] > lookup:
return find_nearest(l[:mid], lookup)
return find_nearest(l[mid:], lookup)
这样:
from datetime import date
d = {
date(2017, 1, 1): 95,
date(2018, 1, 1): 100,
date(2018, 6, 1): 110,
date(2018, 9, 1): 112,
}
d[find_nearest(list(d), date(2018, 8, 1))]
返回:110
答案 1 :(得分:2)
sortedcontainers可能就是您想要的。
它将保持键的排序顺序而不是插入顺序,这不同于$_GET['uuid']
。
安装
if(isset($_GET['uuid'])){
$uuid = $_GET['uuid'];
include('database.php');
$sql = "SELECT * FROM `ips`";
$sql2 = "SELECT * FROM `ips` WHERE `uuid` = '". $uuid ."'";
foreach($mysqli->query($sql) as $row){
$ipss = $row;
}
foreach($mysqli->query($sql2) as $ipsrrr){
$ipsr = $ipsrrr;
}
if($ipss['uuid'] == $uuid && $ipsr['ip'] == $gip){
$allowed = 1;
}else{
header('Location: index.php');
exit(0);
}
}else{
header('Location: index.php');
exit(0);
}
实现您想要的
collections.OrderedDict
此方法的时间复杂度为O(log n)
答案 2 :(得分:0)
修改 我刚刚意识到您需要一个核心模块-我的答案是使用熊猫!
如果您具有唯一的日期值,则可以使用熊猫创建一个使用日期作为索引的数据框:
df = pd.DataFrame.from_dict(rates, orient='index', columns=['value'])
# Convert index to pandas datetime
df.index = pd.to_datetime(df.index)
这将返回:
value
2017-01-01 95
2018-01-01 100
2018-06-01 110
2018-09-01 112
然后:
def lookup(date, df):
# Convert input to datetime
date = pd.to_datetime(date)
# Get closest date in index
closest_date = min(df.index, key=lambda x: abs(x - date))
# Find corresponding index of closest date
index = np.where(df.index == closest_date)[0][0]
# If the date found if greater than the input, then get the date at the index before
if closest_date > date:
index -= 1
return df.iloc[index].value
>> lookup('2018-06-02', df)
Out: 110
>> lookup('2018-05-01', df)
Out: 100
答案 3 :(得分:0)
由于device.writeCharacteristicWithResponseForService()
是通过链表实现的,因此尽管可以利用对键进行排序以减少到的次数,但您无法在不到O( n )的时间内按位置直接检索值。 O(log n )。另请参阅:Accessing dictionary items by position in Python 3.6+ efficiently。
为了提高效率,我建议您使用第三方库(例如Pandas),该库使用保存在连续内存块中的NumPy数组。时间复杂度为O( n ),但是对于较大的输入字典,您应该会看到性能得到改善。
OrderedDict
一种更详细的替代方法:
import pandas as pd
from datetime import date
d = {date(2017, 1, 1): 95, date(2018, 1, 1): 100,
date(2018, 6, 1): 110, date(2018, 9, 1): 112}
df = pd.DataFrame.from_dict(d, orient='index')
df.index = pd.to_datetime(df.index)
my_date = pd.to_datetime(date(2018, 8, 1))
res = df[0].iat[df.index.get_loc(my_date, method='ffill')] # 110
答案 4 :(得分:-1)
您可以尝试.get()方法,该方法仅在存在时返回一个值,否则返回None
import datetime
from datetime import date
def findNearest(somedate, dictionary):
while dictionary.get(somedate) is None:
somedate=somedate-datetime.timedelta(1)
return dictionary.get(somedate)
result=findNearest(date(2017, 1, 3), yourDictionary)
当您打印结果时,它将打印'95',即date(2017,1,1)的值