Python - 检查列表的索引元素是否存在 - 最佳实践?

时间:2014-07-31 16:32:43

标签: python list python-3.x element

我有这样的事情:

for i in range(0,100,5):

    text = ("Price\t",
            foo[i+0].bar, "\t",
            foo[i+1].bar, "\t",
            foo[i+2].bar, "\t",
            foo[i+3].bar, "\t",
            foo[i+4].bar, "\t",
            "Value", "\n")

    file.writelines(text)

我的问题是:我们假设i=0。对于那种情况,我肯定会有foo [0]。但对于指数1,2,3,4,foo可能是空的。例如,如果对于大于2的索引,foo为空,我希望我的文本如下:

text = ("Price\t",
        foo[0].bar, "\t",
        foo[1].bar, "\t",
        foo[2].bar, "\n")

我想过使用异常,但我想,如果我没有所有索引元素,我将无法构造text。 (迭代会停止吗?)那么,最好的做法是什么?我想不出一个简短的方法。基本上我需要的是:

text= ("Price\t",
        ifexist(foo[0].bar, "\t"),
        ifexist(foo[1].bar, "\t"),
        ifexist(foo[2].bar, "\t"),
        ifexist(foo[3].bar, "\t"),
        ifexist(foo[4].bar, "\t"),
        "Value", "\n")

ps:请不要忘记我为了简单而假设i=0。但事实上,一般来说,我将拥有超过一百个价值观。

编辑:通过说“可以为空”,我的意思是说索引可能超出了列表的大小。

edit2:Abot foo:

# start class
class Test:
    def __init__(self, bar, bar2, bar3):
        self.bar= a
        self.bar2= b
        self.bar3= c

# end class    


for i in particular_list:
    # read and parse the input file with indeces obtained from particular_list
    # do calculations for temp_bar,temp_bar2,temp_bar3
    foo.append(Test(temp_bar, temp_bar2, temp_bar3))

4 个答案:

答案 0 :(得分:2)

你会采取不同的方法;您将对原始列表进行切片,并使用csv module来处理制表符分隔和换行符:

import csv

with open('outputfile', 'w', newline='') as file:
    writer = csv.writer(file, delimiter='\t')
    for i in range(0, 100, 5):
        row = foo[i:i + 5]
        writer.writerow(['Price'] + row + ['Value']) 

在列表上切片始终返回一个新的列表对象,但如果使用有效范围之外的切片索引,则结果为较短或空列表:

>>> foo = ['spam', 'ham', 'eggs']
>>> foo[0:5]
['spam', 'ham', 'eggs']
>>> foo[5:10]
[]

同时,csv.writer()对象负责将列表作为制表符分隔的字符串,并在文件中添加换行符。

您可以使用切片,而不是使用csv模块,但可以使用其他采用任意元素列表的技术。例如str.join()

'\t'.join(['Price'] + foo[i:i + 5] + ['Value']) + '\n'

将生成一个制表符分隔值的字符串,并附加换行符。这确实要求传递给str.join()的列表中的所有值都已经是字符串。

答案 1 :(得分:1)

我的建议是,不要依赖索引,而是围绕数据构建代码。如果您没有编制索引,那么您将永远不会遇到IndexError

中的问题

考虑大小为L的列表N,将其平均分配为n。此问题有各种accepted solutions and approaches

我通常宣讲的那个(尽管你可以自由接受任何替代方法)是

izip_longest(*[iter(L)]*n)

所以给定一个列表

L = [a 1 2 3 ... a N ]

这将生成⌊N/n⌋大小相等的块。大小为Mod(N, n)的最后较短列表将附加填充符,默认情况下为无

L = [[a 1 ,a 2 ,a 3 ... a n ], [a 1 2 3 ... a n ],[a 1 2 3 ... a n ] ,.(N Items).. [a 1 2 ,.. a N%n ],无,无..(n个术语)]

现在只需遍历此列表,忽略子列表中的任何Nones

<强>演示

from itertools import izip_longest
class Foo(object):
    def __init__(self, n):
        self.bar = n
foo = [Foo(i) for i in range(12)]
for rows in izip_longest(*[iter(foo)]*5):
    print "Price\t{}".format('\t'.join(str(row.bar)
                       for row in rows
                       if row is not None))

<强>输出

Price   0   1   2   3   4
Price   5   6   7   8   9
Price   10  11

答案 2 :(得分:0)

这取决于foo是什么。如果是listtuple,则不会有空索引。如果是dict,则引用未知密钥将导致KeyError例外。

假设foo是元组列表,您可以轻松打印它;

In [3]: t = range(30)

In [4]: p = [tuple(t[i:i+3]) for i in range(0, len(t), 4)]

In [5]: p
Out[5]: [(0, 1, 2), (4, 5, 6), (8, 9, 10), (12, 13, 14), (16, 17, 18), (20, 21, 22), (24, 25, 26), (28, 29)]

您可以遍历该元组列表并打印它们;

In [6]: for k in p:
    print '\t'.join(['Price'] + [str(i) for i in k] + ['Value'])
   ...:     
Price   0   1   2   Value
Price   4   5   6   Value
Price   8   9   10  Value
Price   12  13  14  Value
Price   16  17  18  Value
Price   20  21  22  Value
Price   24  25  26  Value
Price   28  29  Value

答案 3 :(得分:0)

要扩展我的评论,您可以实现以下内容:

def if_exist(seq, index, attr, default):
    """Return seq[index].attr or default."""
    try:
        return getattr(seq[index], attr)
    except IndexError:
        return default

您可以使用:

if_exist(foo, 0, "bar", "\t")

演示:

>>> if_exist([1, 2, 3], 4, "bar", "\n")
'\n'

但是,我怀疑这是一个XY problem - 如果您提供更多背景信息,我们很可能会帮助您提出一种完全消除此问题的不同方法。