【问题标题】:Setting dictionary values while iterating through a 'for-loop'在迭代“for-loop”时设置字典值
【发布时间】:2019-08-23 21:47:58
【问题描述】:

我正在尝试创建一个嵌套字典,其中包含一组从 for 循环中提取的值,以衡量各种客户-产品配对的增长和收入金额。但是,当我遍历数据框以设置字典的元素时,每个字典元素最终都具有相同的值。这是怎么回事?

我已经尝试过更改列表构建方式的各种元素,但无济于事。

'''
TP_Name = customer name

Service_Level_1 = service name

100.2014 is just a marker to show that someone has started consuming the service

tpdict is already created with necessary nesting below with empty values at each endpoint
'''

for col in pivotdf.columns:
  growthlist = []
  amountlist = []
  first = True
  TP_Name, Service_Level_1 = col.split('___')
  for row in pivotdf[col]:
    if first == True:
      past = row+.00001
      first = False
    if row == 0 and past <.0001 :
      growth = 0
    elif row != 0 and past == .00001:
      growth = 100.2014
    else:
      current = row
      growth = (current-past)/past
    growth = round(growth,4)
    growthlist.append(growth)
    past = row +.00001
    amountlist.append(row)
  tpdict[TP_Name][Service_Level_1]['growth'] = growthlist
  tpdict[TP_Name][Service_Level_1]['amount'] = amountlist

'''
problem: Each value ends up being the same thing
'''

Expected results:

{'CUSTOMER NAME': {'PRODUCT1': {'growth': [unique_growthlist],   'amount': [unique_amountlist]},  'PRODUCT2': {'growth': [unique_growthlist],'amount': [unique_amountlist]}}}

【问题讨论】:

  • 在您的预期结果中,您有两个具有相同值的键,键需要是唯一的
  • 字典是一个键值对(我相信你知道)。如果您尝试使用已存在的键写入字典,它将覆盖该值。
  • @Error - 语法悔恨,这些键具有唯一值,这些值在 TP_Name, Service_Level_1 = col.split('___') 行中的“for-loop”中更改。 @depperm - 预期的结果,每个名称和产品都有唯一的名称,这只是一个示例。将进行修改以使其更加清晰。
  • 尝试复制列表:tpdict[TP_Name][Service_Level_1]['growth'] = list(growthlist) 否则dict 指向的对象是不断被修改的对象
  • @enixon4 是pivotdf 一个实际的pandas.DataFrame 因为看起来你可以通过一些聚合操作来做你正在做的事情,然后to_dict() 它......

标签: python list dictionary for-loop iteration


【解决方案1】:

字典是一个键值对(我相信你可能知道)。如果您尝试使用字典中已存在的键写入字典,则字典将覆盖该键的值。

示例:

d = dict()
d[1] = 'a' # d = {1: 'a'}
d[1] = 'b' # d = {1: 'b'}

您的项目似乎可以很好地使用 python 中的namedtuplenamedtuple 基本上是一个轻量级的类/对象。 我的示例代码可能是错误的,因为我不知道您的 for 循环是如何工作的(评论对每个人都有帮助)。这里所说的只是一个例子。

我只提出这个建议,因为 dictionaries 消耗的内存比它们所持有的对象多约 33%(尽管它们要快得多)。

from collections import namedtuple

Customer = namedtuple('Customer', 'name products')
Product = namedtuple('Product', 'growth amount')

customers = []
for col in pivotdf.columns:
    products = []
    growthlist = []
    amountlist = []
    first = True
    TP_Name, Service_Level_1 = col.split('___')
    for row in pivotdf[col]:
        if first == True:
            past = row + .00001
            first = False
        if row == 0 and past < .0001 :
            growth = 0
        elif row != 0 and past == .00001:
            growth = 100.2014
        else:
            current = row
            growth = (current - past) / past
        growth = round(growth, 4)
        growthlist.append(growth)
        past = row + .00001
        amountlist.append(row)

    cur_product = Product(growth=growthlist, amount=amountlist) # Create a new product
    products.append(cur_product) # Add that product to our customer

# Create a new customer with our products
cur_customer = Customer(name=TP_Name, products=products)
customers.append(cur_customer) # Add our customer to our list of customers

这里的customers 是客户namedtuples 的列表,我们可以将其用作对象。 例如,我们可以这样打印出来。

for customer in customers:
    print(customer.name, customer.products) # Print each name and their products
    for growth, amount in customer.products:
        print(growth, amount) # Print growth and amount for each product.

【讨论】:

  • 命名元组会遇到同样的问题。您应该阅读this article 以了解可变/不可变对象。
  • @JacquesGaudin 除非我遗漏了什么,否则命名元组解决方案会在每个 for 循环迭代中创建新对象并将其附加到列表中。它与当前的问题没有相似之处。最重要的是,它不像字典那样是不可变的。基于这个问题,我看不出它需要可变的原因。
  • 对不起,我不同意。如果命名元组指向一个可变值,则它们是可变的。见trinket.io/python/e6921d8575。您在每次迭代中创建的对象都指向一个在循环执行期间发生变化的列表对象,当循环结束时,它们都指向同一个对象,因此都是相等的。
  • @JacquesGaudin 不可变的定义有很多:stackoverflow.com/a/9756087/8150685。在您的情况下,您认为它不是深度不变的。 python 中的不可变对象可以包含可变对象。 stackoverflow.com/a/9758886/8150685
  • @Error-SyntacticalRemorse,答案很好,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多