为什么在这个循环结束时字典值被覆盖? [英] Why are dictionary values being overriden at the end of this loop?
问题描述
我有一个公共交通站点的词典叫停止。我想复制那些是传输(有多行),以便在这些额外的行的停靠点重复停止。我最初存储这些重复的字典称为duplicateates。但是,在为每个重复停靠点分配相应行的名称后,它们都将被原始停靠点原始列表中的最后一行覆盖。所以我结束了一堆重复停止所有与同一行,而不是一个停止每行。什么是重写这些值?文件l_stops.csv位于 Dropbox 和 bpaste 。
import csv
import random
def stop_coords():
with open('l_stops.csv','rb')as csvfile:
stop_reader = csv.reader(csvfile,delimiter =',',quotechar ='')
stops = {}
for stop_reader:
map_id = row [5]
lines = set b如果row [7] =='true':
lines.add('Blue') )
if row [9] =='true':
lines.add('Green')
if row [10] =='true':
lines.add ('Brown')
if row [11] =='true':
lines.add('Purple')
if row [13] =='true':
lines.add('Yellow')
if row [14] =='true':
lines.add('Pink')
if row [15] =='true' :
lines.add('Orange')
如果map_id不在stops中:
stop_name = row [2] .partition('(')[0] .rstrip b $ b lat = float(row [16] .lstrip(''(')。rpartition(',') .rpartition(',')[2] .strip(')'))
stop = {}
stop ['name'] = stop_name
stop ['lat'] = lat
stop ['lng'] = lng
stop ['x'] = lng
stop ['y'] = lat
stop ['lines'] = lines
stop [map_id] = stop
stop ['duplicate_stops'] = []
elif stops [map_id] line'] = stops [map_id] ['lines']。union(lines)
停止中的项目:
stops [item] ['lines'] = list(stops [item] '])
#为转移的停止添加重复停止(由多行共享)
duplicateates = {}#将保存重复的字典,并添加到停止字典所有重复停止已处理
停止中的项目:
num_lines = len(stops [item] ['lines'])
如果num_lines> 1:#如果一个停靠点有多行
original_lines = stops [item] ['lines']
stops [item] ['lines'] = original_lines [0]
equivalent_map_ids = [item]#创建代表同一站点(但在不同的行)的不同map_ids的列表。列表中的第一个map_id将是原始。
for i in range(num_lines - 1):#为第一行之后的每一行
#创建一个新的map_id,并确保它不与现有的map_id冲突
while True:
new_map_id = str(random.randint(10000,99999))
如果new_map_id不在停止,new_map_id不在重复中:
break
duplicateates [new_map_id] = stops [item] #重复停止
equivalent_map_ids.append(new_map_id)#将新的map_id添加到等效map_ids列表
#将equivalent_map_ids中每个人的duplicateStops值设置为其他站点的map_ids
# equals_map_ids中的第一个map_id是停止字典中的原始值,因此将duplicateStops值设置为列表的其余部分
stops [item] ['duplicateStops'] = equivalent_map_ids [1:]
#对于equals_map_ids中的map_ids的其余部分
j = 1
用于stops中的duplicate_stop [item] ['duplicateStops']:
duplicates [duplicate_stop] ['lines'] = original_lines [ j]
重复[duplicate_stop] ['duplicateStops'] = equivalent_map_ids [:j] + equivalent_map_ids [(j + 1):]#这行也改变了停止[item] ['duplicateStops'], b $ b j + = 1
#在某种程度上,所有重复项都有相同的行(原始'行'列表中的最后一行)
停止在停止[item] ['duplicateStops']:
打印副本[stop] ['name']
打印副本[stop] ['lines']
用于重复项目:
打印项目
打印副本[item] ['name']
打印副本[item] ['lines']
stops.update(重复)
stops ['none'] = {'name' :'none','lat':0,'lng':0,'x':0,'y':0,'lines':['none']}
在调试时,我发现重新分配重复项目[duplicate_stop] ['duplicateStops']也重新分配停靠点[item] ['duplicateStops']。这怎么可能?重复和停止是两个单独的字典。
解决方案然后
重复[duplicate_stop]
和停止[item]
同时 ,好,更改对象。对象不是在作业上自动复制/克隆/复制,或用作函数参数。
有问题的行最有可能
重复[new_map_id] = stops [item]#重复停止
..而且评论是错误,因为发生了没有重复。
问题理解dict.copy() - 浅或深?可能有用;至少它显示如何做一个真正的副本。
I have a dictionary of public transportation stops called stops. I want to duplicate the ones that are transfers (have more than one line) so that there is a duplicate stop in stops for each of those additional lines. I initially store those duplicates in a dictionary called duplicates. However, after I assign the name of the appropriate line to each duplicate stop, they all gets overriden by the last line in the original stop's original list of lines. So I end up with a bunch of duplicate stops all with the same line instead of one stop for each line. What is overriding these values? The file l_stops.csv is on Dropbox and bpaste.
import csv import random def stop_coords(): with open('l_stops.csv', 'rb') as csvfile: stop_reader = csv.reader(csvfile, delimiter=',', quotechar='"') stops = {} for row in stop_reader: map_id = row[5] lines = set() if row[7] == 'true': lines.add('Red') if row[8] == 'true': lines.add('Blue') if row[9] == 'true': lines.add('Green') if row[10] == 'true': lines.add('Brown') if row[11] == 'true': lines.add('Purple') if row[13] == 'true': lines.add('Yellow') if row[14] == 'true': lines.add('Pink') if row[15] == 'true': lines.add('Orange') if map_id not in stops: stop_name = row[2].partition('(')[0].rstrip(' ') lat = float(row[16].lstrip('"(').rpartition(',')[0]) lng = float(row[16].lstrip('"(').rpartition(',')[2].strip(' )"')) stop = {} stop['name'] = stop_name stop['lat'] = lat stop['lng'] = lng stop['x'] = lng stop['y'] = lat stop['lines'] = lines stops[map_id] = stop stop['duplicateStops'] = [] elif stops[map_id]['lines'] != lines: stops[map_id]['lines'] = stops[map_id]['lines'].union(lines) for item in stops: stops[item]['lines'] = list(stops[item]['lines']) # Add duplicate stops for stops that are transfers (shared by multiple lines) duplicates = {} # the dictionary that will hold the duplicates and be added to the stops dictionary after all duplicate stops have been processed for item in stops: num_lines = len(stops[item]['lines']) if num_lines > 1: # if a stop has more than one line original_lines = stops[item]['lines'] stops[item]['lines'] = original_lines[0] equivalent_map_ids = [item] # Make a list of different map_ids that represent the same stop (but on different lines). The first map_id in the list will be the "original" one. for i in range(num_lines - 1): # for each line after the first one # Create a new map_id and make sure it doesn't conflict with an existing map_id while True: new_map_id = str(random.randint(10000, 99999)) if new_map_id not in stops and new_map_id not in duplicates: break duplicates[new_map_id] = stops[item] # duplicate the stop equivalent_map_ids.append(new_map_id) # add the new map_id to the list of equivalent map_ids # Set the duplicateStops value of everyone in equivalent_map_ids's to the other stops' map_ids # The first map_id in equivalent_map_ids is the original one that's in the stops dictionary, so set its duplicateStops value to the rest of the list stops[item]['duplicateStops'] = equivalent_map_ids[1:] # For the rest of the map_ids in equivalent_map_ids j = 1 for duplicate_stop in stops[item]['duplicateStops']: duplicates[duplicate_stop]['lines'] = original_lines[j] duplicates[duplicate_stop]['duplicateStops'] = equivalent_map_ids[:j] + equivalent_map_ids[(j + 1):] # this line also changes stops[item]['duplicateStops'], not sure how j+= 1 # somehow by this point all duplicates have the same line (the last line in the original 'lines' list) for stop in stops[item]['duplicateStops']: print duplicates[stop]['name'] print duplicates[stop]['lines'] for item in duplicates: print item print duplicates[item]['name'] print duplicates[item]['lines'] stops.update(duplicates) stops['none'] = {'name' : 'none', 'lat' : 0, 'lng' : 0, 'x' : 0, 'y' : 0, 'lines' : ['none']}
While debugging, I discovered that reassigning duplicates[duplicate_stop]['duplicateStops'] also reassigns the stops[item]['duplicateStops']. How is that possible? duplicates and stops are two separate dictionaries.
解决方案Then
duplicates[duplicate_stop]
andstops[item]
both name the same object - and mutating the object, well, changes the object. Objects are not automatically copied/cloned/duplicated on an assignment or when used as function arguments.The problematic line is most likely
duplicates[new_map_id] = stops[item] # duplicate the stop
.. and the comment is wrong because there is no duplication that occurs.
The question Understanding dict.copy() - shallow or deep? may be useful; at the very least it shows how to make a real copy.
这篇关于为什么在这个循环结束时字典值被覆盖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!