我想做一些有点棘手的事情,我不确定最好的方法。
我有一个二维数组,其形式为嵌套列表。列表中的每个“行”具有以下结构:
['171000', 'Thing..Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174']
我想要做的是逐行遍历整个数组,并创建一个新行,将第二个位置的字符串拆分为列表中的三个新字符串,结果如下:
['171000', 'Mega~Corporate', 'Mid~Dairy', 'Micro~Cheese', 'Cheese', '0.012174']
我要提几件事。在上面的例子中,我将字符串分成三个子字符串,Mega,Mid,Micro。并非每个字符串都具有“Mid”和“Micro”部分。其中一些字符串可能只是相同格式的较短版本:
'Thing..Mega~Corporate'
对于这种情况,我想插入一个占位符来保留数组中每个元素的位置(以便最终位置的数字始终具有相同的索引)。
我正在使用的数组相当大,超过10万行。任何帮助都会非常感激,因为我真的很挣这个。
答案 0 :(得分:2)
如果Thing..
表示任意文本(不是字符串中的文字数据):
import re
def explode(s, keywords):
for k in keywords:
m = re.search(r'(%s~[^~]*)(?:~|$)' % (re.escape(k),), s)
yield m and m.group(1)
for row in lst:
row[1:2] = explode(row[1], "Mega Mid Micro".split())
import re
from pprint import pprint
def explode(s, keywords):
for k in keywords:
m = re.search(r'(%s~[^~]*)(?:~|$)' % (re.escape(k),), s)
yield m and m.group(1)
lst = [
['171000', 'Thing..Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174'],
['171000', 'Thing..Mega~Corporate', 'Cheese', '0.012174'],
]
print("Before:")
pprint(lst)
for row in lst:
row[1:2] = explode(row[1], "Mega Mid Micro".split())
print("\nAfter:")
pprint(lst)
Before:
[['171000',
'Thing..Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese',
'Cheese',
'0.012174'],
['171000', 'Thing..Mega~Corporate', 'Cheese', '0.012174']]
After:
[['171000',
'Mega~Corporate',
'Mid~Dairy',
'Micro~Cheese',
'Cheese',
'0.012174'],
['171000', 'Mega~Corporate', None, None, 'Cheese', '0.012174']]
答案 1 :(得分:1)
如果你循环浏览它,每次都要点击'..';你可以在一个新的列表中将所有内容连接起来。我不认为有一个更简单的解决方案。然而,速度不是我的专长。
row = ['171000', 'Thing..Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174']
new_row = []
for i in row:
new_row += i.split('..')
最终结果是......
['171000', 'Thing', 'Mega~Corporate~Thing', 'Mid~Dairy~Thing', 'Micro~Cheese', 'Cheese', '0.012174']
如果您不想使用额外的变量,另一种方法是使用reduce
。
row = reduce(lambda x, y: x + y.split('..'), row, [])
我不太清楚代码中“Thing”的重要性,或者为什么它没有出现在输出中。如果你解释它的规则,我会更新我的答案。
答案 2 :(得分:0)
我不认为我真的理解这个问题......但希望这会给你一个提示:
l = ['171000', 'Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174']
strs = l[1].split('..')
l = [l[0]] + strs + l[2:]
print l
答案 3 :(得分:0)
FakeRainBrigand已将其钉住,除非“..”出现在其他元素中。无论如何,我很想比较时间,看看这个想法有多糟糕,这在技术上也更正确:
for row in myfile:
toSplit = row.pop(1) # 1 being the position of the string to manipulate
for fragment in toSplit.split('..'):
row.insert(-2,fragment)
更新:这是timeit所说的:
s1 = """myfile = [ ['171000', 'Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174'] for i in xrange(1,10000) ]
for row in myfile:
toSplit = row.pop(1)
for fragment in toSplit.split('..'):
row.insert(-2,fragment)
"""
s2 = """myfile = [ ['171000', 'Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174'] for i in xrange(1,10000) ]
for row in myfile:
new_row = []
for i in row:
new_row += i.split('..')
"""
>>> t1 = timeit.Timer(stmt=s1)
>>> t2 = timeit.Timer(stmt=s2)
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=1000)/100000)
166.36 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=1000)/100000)
214.22 usec/pass
两者都不是很快,我相信我们可以做得更好。我希望任何基于正则表达式的解决方案都会变慢。 请注意,只要在整个操作过程中字符串保持不变,拆分'..'或拆分'~Thing ..'就完全相同。
答案 4 :(得分:0)
尝试运行此代码:
import re
row = ['171000', 'Thing..Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', 'Cheese', '0.012174']
现在,每行:
col2 = re.split(r'~?Thing\.\.', row[1])[1:]
row[1:2] = col2 + ['placeholder'] * (3 - len(col2))
在最后一行之后,row
将按照您的要求进行,如果第二个位置在拆分后的第二个位置少于3个元素,则甚至用占位符填充。
答案 5 :(得分:0)
这个版本做了很多检查:
def explode_strg(strg):
temp = strg.split('~')
npieces = len(temp)
assert npieces in (6, 4, 2)
result = ['', '', '']
prefix = 'Thing..'
for i in xrange(0, npieces, 2):
k = temp[i]
v = temp[i+1]
assert k.startswith(prefix)
k = k[len(prefix):]
j = i // 2
assert k == ('Mega', 'Mid', 'Micro')[j]
result[j] = k + '~' + v
return result
tests = [
('Thing..Mega~Corporate~Thing..Mid~Dairy~Thing..Micro~Cheese', ['Mega~Corporate', 'Mid~Dairy', 'Micro~Cheese']),
('Thing..Mega~Corporate~Thing..Mid~Dairy', ['Mega~Corporate', 'Mid~Dairy', '']),
('Thing..Mega~Corporate', ['Mega~Corporate', '', '']),
]
for s, elist in tests:
alist = explode_strg(s)
print alist == elist, s, alist