简体   繁体   English

在有序字典中将键元素添加到键值

[英]Adding an element to the key's value in ordered dictionary

I have an ordered dictionary: 我有一个有序的字典:

{'20140106': '82.1000000',
 '20140217': '77.0300000',
 '20140224': '69.6200000',
 '20140310': '46.3300000',
 '20140414': '49.3800000',

Keys are dates: yyyy-mm-dd and i want to store all values of one month in one key: 键是日期:yyyy-mm-dd,我想在一个键中存储一个月的所有值:

{'20140106': '82.1000000',
 '20140217': ['77.0300000','69.6200000',]
 '20140310': '46.3300000',
 '20140414': '49.3800000',

I realized this not very beutiful solution: 我意识到这不是一个非常美妙的解决方案:

val = []   #list, where i put all values for an exact month
previus_key = list(collection.keys())[0]
val.append(collection.get(previus_key))

for key in list(collection.keys())[1:]:
    if (key[4:6]==previus_key[4:6]):    #if it's the same month
        val.append(list(collection.pop(key)))             #remember the value and delete an item
    else:
        collection.update({previus_key:val})   #that means, we jumped to another month, so lets update the values for previus month 
        previus_key = key            #now, start the same algorihtm for a new month.
    val = collection.get(previus_key)

But, i get an error: 'str' object has no attribute 'append' for line val.append(list(collection.pop(key))) . 但是,我得到一个错误: 'str' object has no attribute 'append'为行val.append(list(collection.pop(key))) I researched it, and came to conclusion, that it must not be here! 我研究了它,并得出结论,它一定不能在这里! Because, i append a list to a list! 因为,我将列表附加到列表中! So, please, point to my mistake and give advice, how could i make the code more beutiful. 所以,请指出我的错误并给出建议,我怎样才能使代码更美观。 Thanks! 谢谢!

I think the issue lies in the last line of your code. 我认为问题在于代码的最后一行。 You do assign a string to the variable var there. 你确实为那里的变量var分配了一个字符串。

EDIT : Here is a suggestion which stays close to your original code. 编辑:这是一个与原始代码保持一致的建议。

new_collection = {}
for key in collection:
    month = key[:6]
    if new_collection.get(month) != None:
        new_collection[month].append(collection[key])
    else:
        new_collection[month] = [collection[key]]

Three things : 1) Here the result is a new dictionary instead of the same instance, as I find it generally preferable. 三件事:1)这里的结果是一个新的字典,而不是相同的实例,因为我发现它通常更可取。 2) The keys are only the year and the month, as the day is irrelevant. 2)密钥只是年份和月份,因为这一天是无关紧要的。 3) All the values are lists, instead of a mix of strings and lists. 3)所有值都是列表,而不是字符串和列表的混合。

Here is a better approach. 这是一个更好的方法。 Given a dict of type {str:str}, we can turn the value into a list on inserts while retaining all the functionality of dict by extending the builtin dict class. 给定类型为{str:str}的字典,我们可以将值转换为插入列表,同时通过扩展内置的dict类来保留dict的所有功能。

Here is a demonstration. 这是一个演示。

>>> class CustomDict(dict):
...     def insert(self, key, val): # add a new method, `insert`
...             if self.get(key):
...                     if not isinstance(self.get(key), list):
...                             lst = []
...                             lst.append(self.get(key))
...                             lst.append(val)
...                             self[key] = lst[:] # copy list
...                     else:
...                             self[key].append(val)
...             else:
...                     self[key] = val
...
>>> vars = {'19900326': '372.99101',
...         '19730529': '291.38291',
...         '19430122': '81.248291',
...         '19930227': '192.32919',}
>>> vars2 = CustomDict(vars)
>>> vars2
{'19730529': '291.38291',
 '19900326': '372.99101',
 '19430122': '81.248291',
 '19930227': '192.32919'}
>>> vars2.insert('19730529', '102.88391')
>>> vars2
{'19730529': ['291.38291', '102.88391'],
 '19900326': '372.99101',
 '19430122': '81.248291',
 '19930227': '192.32919'}

In your case, you'll want to inherit from collections.ordereddict 在您的情况下,您将希望从collections.ordereddict继承

As far as the logic of wanting to store all the pieces of data from the same month in the same list, you can pretty easily code that in there. 至于想要将同一个月的所有数据存储在同一列表中的逻辑,您可以很容易地在那里编写代码。 Just to be sure though, it looks like you're currently disregarding year entirely. 但是可以肯定的是,看起来你现在完全无视年份了。 Are you sure all you care about is the same month, even if the data comes from different years? 你确定你所关心的是同一个月,即使这些数据来自不同的年份吗? If not, you should change your logic so that you can differentiate which year. 如果没有,您应该更改逻辑,以便区分哪一年。

Somebody suggested a better representation of the date, as a 3-tuple (year, month, day) . 有人建议更好地表示日期,作为3元组(year, month, day) This is immutable, so it can be your dict key. 这是不可变的,所以它可以是你的dict键。 (Lists are mutable and cannot be dict keys). (列表是可变的,不能是dict键)。

You could add the month-grouping logic to the insert method, or you could move that logic elsewhere in your code. 您可以将月份分组逻辑添加到insert方法,或者您可以将该逻辑移动到代码中的其他位置。

I don't see any advantage of using strings here as keys to represent the date. 我没有看到在这里使用字符串作为表示日期的键的任何优点 This is my solution, but I hope it won't break your current code. 这是我的解决方案,但我希望它不会破坏您当前的代码。

Well, your code shows you're doing so much nesting there: 好吧,你的代码显示你在那里做了很多嵌套:

 val.append(list(collection.pop(key)))

And: 和:

Keys are dates: yyyy-mm-dd and i want to store all values of one month in one key: 键是日期:yyyy-mm-dd,我想在一个键中存储一个月的所有值:

Here's a way to do it: Use tuples for this purpose: 这是一种方法:使用元组实现此目的:

mydict = {(year, month, day): value}

this way not only you're simplifying the problem, but you're also making your code more readable: 这样不仅可以简化问题,还可以使代码更具可读性:

for date in mydict: 
    year  = date[0] 
    month = date[1] 
         ...
    ...process data...

Though keys can only be immutable objects, hence tuples are immutable objects. 虽然键只能是不可变对象,但是元组是不可变对象。

Why not make use of reduce and filter function. 为什么不使用reducefilter功能。 reduce will apply a function to every item in the iterated object, and you can also specify the initial value for reduce reduce会将函数应用于迭代对象中的每个项目,您还可以指定reduce的初始值

from collections import OrderedDict

a = {'20140106': '82.1000000', '20140217': '77.0300000', '20140224': '69.6200000', '20140310': '46.3300000', '20140414': '49.3800000'}


def aggr(result, item):
    key = filter(lambda x: x[:6] == item[0][:6], result.keys())
    if not key:
        result[item[0]] = [item[1]]
    else:
        result[key[0]].append(item[1])
    return result


r = OrderedDict()
print reduce(aggr, a.items(), r)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM