在python中,如何删除列表中满足特定条件的最左/最右元素?
我有一个如下列表:在python中,如何删除列表中满足特定条件的最左/最右元素?,python,Python,我有一个如下列表: ['a'、'b'、'c'、''、''、''] 这是解析“脏”csv文件的结果。我现在想去掉右边的空列。我不能只用计数,因为长度是可变的。我也不能只使用简单的筛选,因为还有一些行是这样的: ['a1'、''c1'、''''、'''.'] 因此,我必须保留右边的空列而不是。有没有一种惯用的方法可以做到这一点?我希望像“removeWhile”这样的函数可以应用到反向列表中 到目前为止,我提出的最好的建议如下: def filterRow(row): row.reverse
['a'、'b'、'c'、''、''、'']
这是解析“脏”csv文件的结果。我现在想去掉右边的空列。我不能只用计数,因为长度是可变的。我也不能只使用简单的筛选,因为还有一些行是这样的:
['a1'、''c1'、''''、'''.']
因此,我必须保留右边的空列而不是。有没有一种惯用的方法可以做到这一点?我希望像“removeWhile”这样的函数可以应用到反向列表中
到目前为止,我提出的最好的建议如下:
def filterRow(row):
row.reverse()
blanks = 0
for x in row:
if x == '':
blanks += 1
else:
break
row.reverse()
return row[0:-blanks]
也许是这样的
>>> l = ['a', 'b', 'c', '', '', '']
# iterate through the list in reverse...
>>> for v in l[::-1]:
# when we encounter an element that's not empty, exit the loop
... if v:
... break
# otherwise pop the last element off the end of the list
... l.pop()
>>> l
['a', 'b', 'c']
如果出于某种原因,您不想在适当的位置执行此操作,请按以下方式执行:
def filterRow(row):
row = list(row)
while row[-1] == "":
row.pop()
return row
从列表末尾弹出非常快,虽然计算最后一个索引和执行切片可能会稍微快一点,但这也会导致代码更长、更复杂、更难读取。因此,现在就使用可读版本,只考虑一旦确定它是实践中的一个重要瓶颈就改变它。
为了使函数更加直观,为什么不将其称为rstrip
而不是filterRow
,因为它与str.rstrip
对字符串的作用几乎相同?虽然@Lauritz V.Thaulow对您的问题有最清晰的理解,但我认为您可能问错了问题。相反,您应该在读取csv时去掉空列,而不是在您已经将其转换为列表之后。然后一个简单的line.rstrip(',\n')
就可以了
In [1]: lst = ['a1', '', 'c1', '', '']
In [2]: def remove_while(lst):
...: return ','.join(lst).rstrip(', ').split(',')
In [3]: remove_while(['a1', '', 'c1', '', ''])
Out[3]: ['a1', '', 'c1']
所以你可以:
with open('test.csv') as f:
for line in f:
print line.rstrip(', \n').split(',')
#['a1', '', 'c1']
#['a', 'b', 'c']
类似于此,无需创建任何新字符串、列表或使用反转:
In [138]: def remove_while(lis):
.....: le=len(lis)
.....: ind=0
.....: for i in xrange(le-1,-1,-1):
.....: if lis[i]!="":
.....: break
.....: else:
.....: ind+=1
.....: del lis[-ind:]
.....: return lis
.....:
In [139]: remove_while(['a', 'b', 'c', '', '', ''])
Out[139]: ['a', 'b', 'c']
In [140]: remove_while(['a1', '', 'c1', '', ''])
Out[140]: ['a1', '', 'c1']
In [141]: remove_while(['', '', '', '', ''])
Out[141]: []
下面是一个使用单个切片的简洁实现:
def filterRow(row):
rightmost = next(i for i in reversed(xrange(len(row))) if row[i])
del row[rightmost + 1:]
# or, non-destructively: return row[:rightmost + 1]
说明:
以相反的顺序生成列表索引;与'xrange(len(row)-1,-1,-1)相同,但可读性更强reversed(xrange(len(row))
- 如果行[i]是一个生成器表达式,它从右向左遍历索引,跳过空索引,则索引中的i为i
获取生成表达式的第一个元素。应用于上述生成器表达式,它返回最右边非空元素的索引next(iterable)
del row[rightmest+1:][/code>删除行末尾的所有空元素。(或者,
返回最右边非空元素之前的所有元素。)return row[:rightmest+1]
def strip(xs, predicate=lambda x: not x):
"""Given a sequence, remove leading/trailing items that match the predicate."""
m = [bool(predicate(x)) for x in xs]
try:
a = m.index(False)
b = m[::-1].index(False)
return xs[a:len(xs)-b]
except ValueError:
return []
print strip(['','',1,2,'',3,4,0,None,'','']) # [1, 2, '', 3, 4]
print strip([1,2,10,20,3,30,5,6], lambda x: x < 10) # [10, 20, 3, 30]
print strip([10,20,3,30], lambda x: x < 10) # [10, 20, 3, 30]
print strip([1,2,3], lambda x: x < 10) # []
def strip(xs,谓词=lambda x:not x):
“”“给定一个序列,请删除与谓词匹配的前导/尾随项。”“”
m=[bool(谓词(x))表示xs中的x]
尝试:
a=m.索引(假)
b=m[:-1]。索引(False)
返回xs[a:len(xs)-b]
除值错误外:
返回[]
打印条(['','',1,2',,3,4,0,无,'','')#[1,2',,3,4]
打印条([1,2,10,20,3,30,5,6],λx:x<10)#[10,20,3,30]
打印条([10,20,3,30],λx:x<10)#[10,20,3,30]
打印条([1,2,3],λx:x<10)#[]
+1,非常优雅。演示了切片方法,但索引计算很长,很难理解,或者两者都很难理解。+1,但请注意,当所有列都为空时,这会中断。@root将条件更改为,而行和行[-1]==“”
,但将这样一个优雅的解决方案弄得乱七八糟将是一件憾事——至少我的直觉是OP的行从来都不是空的。这个解决方案的问题是它假定了一个固定的CSV语法。尽管名称不同,CSV支持许多不同的字段分隔符(至少在欧洲版本中,Excel默认为;
,因为在大多数欧洲语言中,是十进制分隔符)。然后是引号,它可以创建不同的方式来表示空列。除非您自己生成输入CSV,否则处理它应该留给CSV读取器。@user4815162342-这只是一个玩具示例。无论如何,您仍然可以将CSV.reader
与类似的生成器一起使用:CSV.reader(line.rstrip(',\n'))对于f中的行)
-您仍然需要指定分隔符,但通常在读取文件之前您知道格式。但这正是问题所在-您通常不知道将遇到的CSV方言,CSV
模块会自动为您检测它。@user4815162342-当您使用嗅探器时,您的意思是什么?我几乎从未见过使用过它…但您是正确的t、 如果你想使用自动检测,这是不合适的。否则我会说它是更有效和可读的。
def strip(xs, predicate=lambda x: not x):
"""Given a sequence, remove leading/trailing items that match the predicate."""
m = [bool(predicate(x)) for x in xs]
try:
a = m.index(False)
b = m[::-1].index(False)
return xs[a:len(xs)-b]
except ValueError:
return []
print strip(['','',1,2,'',3,4,0,None,'','']) # [1, 2, '', 3, 4]
print strip([1,2,10,20,3,30,5,6], lambda x: x < 10) # [10, 20, 3, 30]
print strip([10,20,3,30], lambda x: x < 10) # [10, 20, 3, 30]
print strip([1,2,3], lambda x: x < 10) # []