Python-检查列表的索引元素是否存在-最佳实践?
我有这样的想法:Python-检查列表的索引元素是否存在-最佳实践?,python,list,python-3.x,element,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")
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= ("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
。但事实上,一般来说,我会有上百个值
编辑:我说“可以是空的”,意思是索引可能超出了列表的大小
编辑2: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))
你会采取不同的方法;您将对原始列表进行切片,并使用来处理选项卡定界和换行:
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
模块不同,您仍然可以使用切片,但可以使用其他技术获取任意元素列表。例如:
'\t'.join(['Price'] + foo[i:i + 5] + ['Value']) + '\n'
将生成一个由制表符分隔的值组成的字符串,并附加一个换行符。这确实要求传递给str.join()
的列表中的所有值都已经是字符串。这取决于foo
是什么。如果是列表
或元组
,则不会有空索引。如果是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
要扩展我的评论,您可以实现如下内容:
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'
然而,我怀疑这是一个问题——如果您提供更多的背景信息,我们可能会帮助您提出一种完全解决此问题的不同方法。我的建议是,不要依赖索引,而是围绕数据构建代码。如果您没有索引,那么在IndexError中就永远不会有问题
考虑将一个大小为N
的列表L
按大小N
平均划分。这个问题有多种原因
我通常鼓吹的方法(尽管你可以自由接受任何其他方法)是
所以给出了一个清单
L=[a1,a2,a3…aN]
这将产生⌊不适用⌋ 大小相同的块。最后一个较短的sizeMod(N,N)
列表将附加一个填充符,在本例中默认为None
L=[[a1,a2,a3…an],[a1,a2,a3…an],[a1,a2,a3…an],(N项)…[a1,a2,…an%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
最简单的解决方法是尝试,然后捕获索引器之外的。但是你最好改变你的数据结构,比如元组列表而不是一个长而平的列表。你说的空是什么意思?你的意思是索引超出了列表的大小吗?或者foo[4]
的值是None
?或者foo[4]
的值是'
?@jornsharpe使用类结构来存储元素似乎是一件很好的事情。但是,这是一个直觉的决定。我尝试使用try&except indexer,但是在这种情况下,如果缺少一个元素,我将丢失文本。你能告诉我怎么用吗?@Robᵩ 我想说的是索引是否超出了列表的大小。谢谢,我将编辑这个问题。@FrankBrewer您的Test
类可能是一个元组,因为它不包含任何方法。这将使foo
成为一个元组列表,可以通过迭代列表和join
-ing元组轻松处理。添加了关于foo
Price 0 1 2 3 4
Price 5 6 7 8 9
Price 10 11