Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用嵌套for循环迭代csvDictReader_Python_Csv_For Loop - Fatal编程技术网

Python 使用嵌套for循环迭代csvDictReader

Python 使用嵌套for循环迭代csvDictReader,python,csv,for-loop,Python,Csv,For Loop,我很难理解如何正确地迭代csvDictReader对象。我试图返回每个绑定到特定用户定义数据代码的csv值。因为我是从一个web查询生成dict,所以我希望在内存中重新使用它,而不是再次轮询web以查找内存中已经存在的数据 import sys, csv, urllib2 class SmfImpl(): def __init__( self, ctx ): self.ctx = ctx self.csv_dict = [] self.f

我很难理解如何正确地迭代csvDictReader对象。我试图返回每个绑定到特定用户定义数据代码的csv值。因为我是从一个web查询生成dict,所以我希望在内存中重新使用它,而不是再次轮询web以查找内存中已经存在的数据

import sys, csv, urllib2
class SmfImpl():

    def __init__( self, ctx ):
        self.ctx = ctx
        self.csv_dict = []
        self.flag = ['Not Available', '']
        self.ticker = 'XOM'

    def getMorningKey(self, datacode):
        return fetch_keyratios(self, datacode)

#these functions are not in the SmfImpl class because they're from a seperate file
def query_morningstar(self, url_ending): 
        url = 'http://financials.morningstar.com/ajax/exportKR2CSV.html?&callback=?&t=XNYS:%s%s' % (self.ticker, url_ending)
        req = urllib2.Request(url)
        response = sniff_query(req)
        response.readline()
        return csv.DictReader(response)

def sniff_query(req):
    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError:
        return 'Check Connection'
    sniff = response.readline()
    if str(sniff) == '':
        return 'Not Available'
    return response

def fetch_keyratios(self, datacode):
    if datacode < 1 or datacode > 990:
        return 'Invalid Datacode'
    #check if we already have the data we need
    if self.flag[0] == 'Check Connection' or self.flag[0] == 'Not Available' or self.flag[1] != self.ticker:
        #query remote and check for errors
        self.csv_dict = query_morningstar(self,'&region=usa&culture=en-US&cur=USD&order=desc')
        if self.csv_dict == 'Check Connection' or self.csv_dict == 'Not Available':
            self.flag[1] = ''
            return self.csv_dict
        else:
            self.flag[0] = ''
            self.flag[1] = self.ticker
    return sort_keyratios(self, datacode)

def sort_keyratios(self, datacode):       
    counter = 1
    skipped = 0
    skip_lines = [15, 16, 26, 36, 37, 57, 58, 64, 65, 86, 91, 92]            
    #iterate through returned dict line by line
    for line in self.csv_dict:
        for item in skip_lines:
            if counter == item:
                skipped += 1
        for val in range(1, len(line)):
            #match year values to datacodes
            if datacode == val:
                return self.csv_dict.fieldnames[val]
            #match data values to datacodes
            if datacode-((counter-skipped)*(len(line)-1)) == val:
                return line[self.csv_dict.fieldnames[val]]
        counter += 1
    return 'No Data'

if __name__ == "__main__":
    smf = SmfImpl(sys.argv)
    ticker = 'XOM'
    for val in range (1,24):
        print ticker, val,':', smf.getMorningKey(val)
我想要得到的是:

XOM 1 : TTM
XOM 2 : 2012-12
XOM 3 : 2011-12
XOM 4 : 2010-12
XOM 5 : 2009-12
XOM 6 : 2008-12
XOM 7 : 2007-12
XOM 8 : 2006-12
XOM 9 : 2005-12
XOM 10 : 2004-12
XOM 11 : 2003-12
XOM 12 : 443,708
XOM 13 : 482,295
XOM 14 : 486,429
XOM 15 : 383,221
XOM 16 : 310,586
XOM 17 : 477,359
XOM 18 : 404,552
XOM 19 : 377,635
XOM 20 : 370,680
XOM 21 : 298,035
XOM 22 : 246,738
XOM 23 : 27.8

编辑:我正在尝试将原始csv的每行数据代码分组映射。e、 g年将是数据代码1到11(TTM到2003-12),收入将是数据代码12到22(443708到246738),等等。最终这些数据代码将被移动到用户输入,因此可以以任何顺序访问它们。

我将这样做。它将产生你想要的输出。我对代码进行了一些重新格式化,以便更好地适应stackoverflow上的代码列表框。棘手的部分是找出
datacode
row,column
的映射,这些数据被读取到内存中的矩阵中

import sys, csv, urllib2
class SmfImpl():
    def __init__( self, ctx ):
        self.ctx = ctx
        self.csv_reader = ''
        self.flag = ['Not Available', '']
        self.ticker = 'XOM'

    def getMorningKey(self, datacode):
        return fetch_keyratios(self, datacode)

#these functions are not in the SmfImpl class because they're in a seperate file
def query_morningstar(self, url_ending):
    MORNING_STAR = 'http://financials.morningstar.com/ajax/exportKR2CSV.html'
    url = MORNING_STAR + '?&callback=?&t=XNYS:%s%s' % (self.ticker, url_ending)
    req = urllib2.Request(url)
    response = sniff_query(req)
    response.readline()
    return csv.reader(response)

def sniff_query(req):
    try:
        response = urllib2.urlopen(req)
    except urllib2.URLError:
        return 'Check Connection'
    sniff = response.readline()
    if str(sniff) == '':
        return 'Not Available'
    return response

def fetch_keyratios(self, datacode):
    if datacode < 1 or datacode > 990:
        return 'Invalid Datacode'
    #check if we already have the data we need
    if(self.flag[0] == 'Check Connection' or
       self.flag[0] == 'Not Available' or self.flag[1] != self.ticker):
        #query remote and check for errors
        self.csv_reader = query_morningstar(self,
                                '&region=usa&culture=en-US&cur=USD&order=desc')
        if(self.csv_reader == 'Check Connection' or
           self.csv_reader == 'Not Available'):
            self.flag[1] = ''
            return self.csv_reader  # actually response status message
        else:
            self.flag[0] = ''
            self.flag[1] = self.ticker
            # read entire dataset in memory skipping lines as neccessary
            self.data = [row[1:] for row in self.csv_reader if len(row) == 12]

    return sort_keyratios(self, datacode)

def sort_keyratios(self, datacode):
    # convert datacode to row, column and return data in that position of list
    row, col = divmod(datacode-1, 11)
    return self.data[row][col]

if __name__ == "__main__":
    smf = SmfImpl(sys.argv)
    ticker = 'XOM'
    for val in range(1, 24):
        print ticker, val,':', smf.getMorningKey(val)

马蒂诺发布的答案是正确的。为了完成并获得我最初寻找的功能,我将sort_keyratios更改为以下内容:

def sort_keyratios:    
    #define rows that have no useful data   
    skip_list = [16,17,18,28,29,38,39,40,41,46,51,56,61,62,63,69,70,71,92,93,98,99,100]
    skipped = 0
    # match datacode to row, column and return data in that position of list
    for row in range(0,109):
        if row in skip_list:
            skipped+=11
            continue
        for col in range(0,12):
            if datacode == col+(11*row)-skipped:
                return self.data[row][col]

这是为了响应您在自己问题的答案中对
sort\u keyrations()
所做的修改。如果你觉得额外的信息有用的话,你还可以选择其他的东西

无论如何,您可以通过构建一个字典,将每个
datacode
映射到
(行,列)
对一次,然后使用这个先前构建的表来查找函数中的值,从而更高效地完成正在做的事情。为了方便起见,我添加了一个名为
create\u datacode\u map()
的新函数

以下是它的使用方法:

def create_datacode_map():
    """ Create dictionary mapping datacodes to (row, col) in data. """
    # define rows that have no useful data
    skip_list = {16, 17, 18, 28, 29, 38, 39, 40, 41, 46, 51, 56, 61, 62, 63, 69,
                 70, 71, 92, 93, 98, 99, 100}
    def find_row_col(datacode):
        skipped = 0
        # match datacode to row, column
        for row in xrange(0, 109):
            if row in skip_list:
                skipped += 11
                continue
            for col in xrange(0, 12):
                if datacode == col + (11*row) - skipped:
                    return row, col

    # create and return the dictionary
    return {datacode: find_row_col(datacode) for datacode in xrange(1, 910)}

def sort_keyratios(self, datacode):
    # convert datacode to row, column and return data in that position of list
    if not hasattr(self, 'datacode_map'):
        self.datacode_map = create_datacode_map()
    row, col = self.datacode_map[datacode]  # lookup conversion
    return self.data[row][col]

所示的
sort\u keyrations()
版本在每次调用时检查是否存在
self.datacode\u map
,如果不存在则创建它。如果在
fetch\u keyrations(()
so
sort\u keyrations()中已经这样做了,那么效率会更高
可以假设它存在,而不必每次调用时都检查它。

val/datacodes是否总是按升序访问?是否可以将整个csv读取到内存中?否,main中定义的ticker和val最终都将移动到user input/sys.argv,因此可以按任何顺序访问值r、 首先,这意味着每次至少重新读取csv数据的一部分,因为
csv.DictReader
以顺序方式访问数据——这就是为什么我建议将整个数据读取到内存中,允许随机访问(以及在调用之间保留它)。此外,您的问题还需要添加其他信息来解释数据代码到csv文件中位置的映射,因为代码和其中的一些注释不够清晰。坦白地说,我不清楚您为什么要使用
csv.DictReader
来尝试此操作。我编辑了原始帖子以澄清这一点数据代码映射。我最初将其实现为1 urlrequest->1脚本输出,csvDictReader似乎是正确的方法。我认为现在我在本地重新使用数据,csvDictReader可能不是最好的方法,但我不确定如何按照您的建议在内存中实现此功能。好的,这很有帮助。如果在这种情况下,
XOM 23
的期望值不应该是
27.8
而不是
28.7
?另外,
计数器也是
排序键比率()
这是您自己试图解决问题的产物?这让我走上了正确的道路。真的,非常感谢。我发布了一个答案,它完成了我正在寻找的功能,以防对其他人有所帮助。这感觉就像回到了一个dict的完整循环映射。我相信您已经推断出我正在学习python谢谢你的代码中的解释和微妙之处,它们帮助我指导了我自己的学习(即
xrange()
vs
range()
,尽管我可能会发现自己受制于Python 3,所以可能会坚持
range()
)。你为什么要使用
find\u row\u col()
是一个子函数,而不是将该代码留在
create\u datacode\u map()
中?是的,这是另一个字典,但它的用途完全不同。Python有从版本2转换到版本3的工具,可以修复
xrange
的使用,因此我不会因此而避免它。我制作了
find\u row\u col()
一个嵌套函数,因为它只由
create\u datacode\u map()
调用,并且它允许在函数本身之外创建
skip\u list
,而不是每次调用它。
def create_datacode_map():
    """ Create dictionary mapping datacodes to (row, col) in data. """
    # define rows that have no useful data
    skip_list = {16, 17, 18, 28, 29, 38, 39, 40, 41, 46, 51, 56, 61, 62, 63, 69,
                 70, 71, 92, 93, 98, 99, 100}
    def find_row_col(datacode):
        skipped = 0
        # match datacode to row, column
        for row in xrange(0, 109):
            if row in skip_list:
                skipped += 11
                continue
            for col in xrange(0, 12):
                if datacode == col + (11*row) - skipped:
                    return row, col

    # create and return the dictionary
    return {datacode: find_row_col(datacode) for datacode in xrange(1, 910)}

def sort_keyratios(self, datacode):
    # convert datacode to row, column and return data in that position of list
    if not hasattr(self, 'datacode_map'):
        self.datacode_map = create_datacode_map()
    row, col = self.datacode_map[datacode]  # lookup conversion
    return self.data[row][col]