2017-08-25 116 views
0

我想找到类中第二个属性的对象,使第一个属性具有特定的值。根据该对象的第二个属性访问python对象的属性

Class Day(object): 
    def __init__(self, a_datetime_date): 
     self.date = a_datetime_date 
     self.colour = None 

我现在实例一大堆对象在一个循环:

for x in a_list_of_dates: 
    some_day = Day(x) 
    some_day.colour = 'Red' # or some other values depending on the details 

是相当新的对象,我只是救了他们的字典。 {'1': <__main__.Day object at 0x7f9a444cacd0>, '2': <__main__.Day object at 0x7f9a447cacd0>, etc}

现在有一个简单的方法可以让我检索对应于日期范围的colour?或者,也许,更简单的一个日期?

我只能想办法像sorted(dict.iteritems()),然后通过列表检查day_object.date一个接一个。如果是我想要的日期,那么使用day_object.colour来查找颜色。

的问题的答案可能有两种形式:

  1. 一种更好的方式来存储/访问几百对象(不是字典等)
  2. 一个查询在字典中的对象的方式以获得我感兴趣的日子的颜色。

谢谢。

编辑:在简化一个小问题时,我没有使用类的动机。 “日”对象实际上有15个属性和2个方法(不仅仅是colour)。所以@科尔的建议是好的,但没有这么多的属性。这些对象用于计算各种事物:300天中有多少是休息时间?有多少天是半天?也许我被困在使用复杂的列表/字典和移动到完整的ORM之间?

+0

它几乎听起来像是你想要一个ORM。 –

回答

2

我认为你可以使用bisectOrderedDict

import bisect 
from collections import OrderedDict 

def foo(date): 
    day = Day(date) 
    day.colour = 'Red' # or some other values depending on the details 
    return day 

container = OrderDict({date: foo(date) for date in sorted(date_list)}) 

keys = list(container.keys()) 

# find by range of dates 

start_index = bisect.bisect_left(keys, start_date) 
end_index = bisect.bisect(keys, end_date) 

for index in range(start_index, end_index); 
    print(container[keys[index]].colour) 

# find by a single date 

print(container[single_date].colour) 
0
  1. 你确定你不想要一个数组吗?数据结构可以轻松处理几百个对象,但在这里使用数组更有意义。

  2. 我会用filter

filter(lambda day: min_date < day.date < max_date, array_of_dates)

注意,这是假设你有日期的数组。


写在那之后的想法来找我:为什么不与对象废除完全,只是有键为DateTime对象,并作为颜色值的字典?尽管如此,你仍然需要filter来获得一个范围(它应该比至少排序更快)。

+0

这是有道理的,重读我的问题。请参阅上面的评论以获取有关问题实际复杂性的更多详细信息。 – Massagran

+0

我会跟@ stamaimer的解决方案去自己。有序的词典似乎更合理。 – cole

0

也许你不应该在这里使用一个类,如果你想要的是字典。有一个good video about this on youtube。与列表类相比,使用列表列表更容易。你甚至可以有一个字典,每个关键字都是日期,如果每个关键字都是唯一的话。

当你说你'把他们保存在字典'中是什么意思?你把每个班的副本当作一个字典,每个都有一个数字键?这是浪费内存和CPU时间。

1

首先,列表是你想要做什么更好的数据结构。除非这些键有一些在问题中不明显的含义。

你可以做你想做的与列表理解(一旦一切都在一个列表)。

foo = list() 
for date in dates: 
    some_day = Day(date) 
    some_day.colour = 'Red' 
    foo.append(some_day) 

values = [x.colour for x in foo if date_1 <= x.date <= date_2] 
+0

这里的代码(https://gist.github.com/alphydan/bd3d5cf1b7b6acf3b76f818c73b5965f)更多的上下文。我简化了这里的密钥以尽量保持简单。那么嵌套列表的列表将是另一种选择? – Massagran

+0

不幸的是,还依赖于其他3个或4个属性。我在这里简化了课程,但必须在这些日期之间,不是假期,不是半天,不是假期学习日,不是周末......然后找到“颜色”和数字当然等等原则是相同的,但取决于许多属性。 – Massagran

1

我不知道你打算用这个做除了看颜色什么。尝试使用颜色散列字典;这将让创建色彩和日之间的关系:在重新

from collections import defaultdict 
color_dict = defaultdict(list) 

for x in a_list_of_dates: 
    some_day = Day(x) 
    some_day.colour = 'Red' # Not sure how you're planning to make these assignments. 
    colour_dict['Red'].append(some_day) 

# Look up all Day objects colored Red 
colour_dict['Red'] 

:“要查询的字典获得的日子,我很感兴趣的颜色对象的一种方式” 如果你想要去与当前词典数据结构 - 我不会推荐:):

[day for day in dict_of_days.values if day.colour='Red'] 

但是你会发现,你的钥匙没有太大的意义或实用工具以这种形式,所以我'd建议将它存储在列表中而不是字典中。一旦在列表中,你可以运行下面让所有日子,是红色:

[day for day in list_of_days if day.colour='Red'] 

替代解决方案

  1. 存储你的数据在大熊猫数据帧http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html。通过这种方式,您可以以表格格式(即列= [日,颜色,IsHalfDay等])对数据进行切片和切块。
  2. 对于快速轻量级的ORM解决方案,尝试一对多(逐日颜色)或多对多(逐日)关系http://docs.sqlalchemy.org/en/latest/orm/basic_relationships.html