从字符串列表中删除整数
Posted
技术标签:
【中文标题】从字符串列表中删除整数【英文标题】:Removing integers from a list of list of strings 【发布时间】:2016-04-03 12:14:00 【问题描述】:我有一个要删除整数的字符串列表列表
[[[u'HH', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
以上列表应该返回
[[[u'HH', u'AH', u'L', u'OW'], [u'HH', u'EH', u'L', u'OW']]]
我尝试过使用过滤器
filter(lambda i: not str.isdigit(i), phoneseqList[0])
但这似乎不起作用
【问题讨论】:
你能提供你使用的真实代码吗?filter
本身不会告诉我们您是否未能以其他方式正确使用它;已经存在明显的问题(phoneseqList[0]
可能是错误的,因为单一级别的索引仍在使用list
的list
的unicode
)。另外,需要明确的是,这是 Python 2 还是 Python 3 代码?字符串上的 u
前缀使 Py2 成为可能,但在 Py2 和 Py3 中都是合法的。
【参考方案1】:
如果数字总是在最后,你可以使用str.rstrip
:
>>> phone_seq_list = [['HH', 'AH0', 'L', 'OW1'], ['HH', 'EH0', 'L', 'OW1']]
>>> [[s.rstrip('0123456789') for s in l] for l in phone_seq_list]
[['HH', 'AH', 'L', 'OW'], ['HH', 'EH', 'L', 'OW']]
【讨论】:
请注意,这假设数字字符只会出现在每个字符串的尾部,这恰好是给定示例的情况,但未在问题中指定(仅提及删除整数)。 你说得对,我只是修改了我的答案来解释这一点。【参考方案2】:您当前正在查看第一个嵌套list
中的每个字符串,它本身就是list
,因此缺少isdigit()
方法。您需要处理每个字符。
phoneseqList = [[[u'HH', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
newlist = [[[''.join(element for element in item if not element.isdigit()) for item in sublist] for sublist in phoneseqList[0]]]
结果:
>>> newlist
[[[u'HH', u'AH', u'L', u'OW'], [u'HH', u'EH', u'L', u'OW']]]
【讨论】:
【参考方案3】:看到数字位于单词的末尾,并且您想要的每个项目最多 2 个字符,您可以对字符串进行切片以仅提取前两个字符。这会遗漏最后的数字。
l = [[u'HH', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]
newL = []
for sublist in l:
tempL = []
for item in sublist:
tempL.append(item[:2])
newL.append(tempL)
print newL
【讨论】:
【参考方案4】:对于任意嵌套的字符串列表,这里有一个递归解决方案,它将从所有字符串中删除任何数字
def remove_digits(i):
if isinstance(i, list):
return [remove_digits(j) for j in i]
else:
return ''.join(j for j in i if not j.isdigit())
例子
>>> l = [[[u'HH', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
>>> remove_digits(l)
[[['HH', 'AH', 'L', 'OW'], ['HH', 'EH', 'L', 'OW']]]
编辑 要为每个字符串添加扩展名,您可以执行相同的想法
def add_ext(i, ext):
if isinstance(i, list):
return [add_ext(j, ext) for j in i]
else:
return i + ext
所以你可以说
>>> add_ext(l, '.jpeg')
【讨论】:
在将内容附加到列表时,同样的逻辑是否有效?我现在想为每个元素添加一个“.jpeg”字符串,但我不确定 join 方法在 else 中做了什么 @NeptuneGamer 是的,同样的想法也适用,请参阅我的编辑。 如果您愿意,您也可以一次完成所有操作,所以else
的情况可能是''.join(blah) + ext
为什么不return re.sub("\d+","",i)
【参考方案5】:
进一步嵌套循环:
from itertools import filterfalse # ifilterfalse on Python 2
for sublist1 in toplist:
for sublist2 in sublist1:
for i, s in enumerate(sublist2):
sublist2[i] = ''.join(let for let in s if not let.isdigit())
是的,您可以使用所有嵌套列表推导中最糟糕的一种来创建一个新的 list
或 list
或 list
s 并替换现有的,但在这种情况下,它更直接/可读使用显式循环改变现有的list
。如果您以后需要未修改的版本,您可以随时copy.deepcopy
原始***list
。
【讨论】:
【参考方案6】:这应该可以解决您的问题:
def strip_digits(text):
return ''.join([c for c in text if not c.isdigit()])
def filter_list(outer):
return [[strip_digits(i) for i in inner] for inner in outer]
如果您喜欢 TDD 方式,请使用随附的单元测试 :)
class FilterListTest(unittest.TestCase):
def test_filter_list(self):
# Arrange
actual = [[u'HH', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]
expected = [[u'HH', u'AH', u'L', u'OW'], [u'HH', u'EH', u'L', u'OW']]
# Act & Assert
self.assertEquals(filter_list(actual), expected)
【讨论】:
【参考方案7】:您可以使用str.translate
删除数字:
l = [[[u'HH2', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
tbl = ord(d): u"" for d in u"0123456789"
for sub in l:
sub[:] = [[s.translate(tbl) for s in w] for w in sub]
输出:
[[[u'HH', u'AH', u'L', u'OW'], [u'HH', u'EH', u'L', u'OW']]]
如果你想任意嵌套:
l = [[[u'HH2', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
def rem_d(l, tbl):
if isinstance(l, list):
return [rem_d(ele, tbl) for ele in l]
return l.translate(tbl)
tbl = ord(d): u"" for d in u"0123456789"
print(list(rem_d(l, tbl)))
输出:
[[[u'HH', u'AH', u'L', u'OW'], [u'HH', u'EH', u'L', u'OW']]]
翻译会比遍历每个数字快很多:
In [13]: l = [[[u'HH2', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
In [14]: l = [l[0] for _ in range(100000)]
In [15]: timeit rem_d(l, tbl)
1 loops, best of 3: 777 ms per loop
In [16]: timeit remove_digits(l)
1 loops, best of 3: 1.83 s per loop
In [17]: remove_digits(l) == rem_d(l,tbl)
Out[17]: True
【讨论】:
【参考方案8】:我同意@CoryKramer 关于递归实现的观点(除非情况始终是列表列表的列表)。以下实现类似,仅在必要时保留 unicode 编码。
import re
lst = [[[u'HH', u'AH0', u'L', u'OW1'], [u'HH', u'EH0', u'L', u'OW1']]]
def removeDigits(lst):
for i,l in enumerate(lst):
if isinstance(l, list):
removeDigits(l)
else:
lst[i] = re.sub('[0-9]+','', l)
removeDigits(lst)
print lst
输出
[[[u'HH', u'AH', u'L', u'OW'], [u'HH', u'EH', u'L', u'OW']]]
【讨论】:
以上是关于从字符串列表中删除整数的主要内容,如果未能解决你的问题,请参考以下文章