我有一个由空格分隔的单行上的大型名称和值文件:
name1 name2 name3....
在长名单后面是与名称对应的值列表。值可以是0-4或na。我想要做的是合并数据文件,并在值为na
时删除所有名称和值。
例如,此文件中的最后一行名称是这样的:
namenexttolast nameonemore namethelast 0 na 2
我想要以下输出:
namenexttolast namethelast 0 2
我如何使用Python做到这一点?
答案 0 :(得分:5)
假设您将名称读入一个列表,然后将值读入另一个列表。获得names
和values
列表后,您可以执行以下操作:
result = [n for n, v in zip(names, values) if v != 'na']
result
现在是所有名称不是“na”的名称的列表。
答案 1 :(得分:4)
s = "name1 name2 name3 v1 na v2"
s = s.split(' ')
names = s[:len(s)/2]
values = s[len(s)/2:]
names_and_values = zip(names, values)
names, values = [], []
[(names.append(n) or values.append(v)) for n, v in names_and_values if v != "na"]
names.extend(values)
print ' '.join(names)
<强>更新强>
保罗的建议后略有改善。我确信列表理解是相当单一的,因为它利用list.append
返回None
的事实,因此将评估append
个表达式和None
值的列表将被建造并立即扔掉。
答案 2 :(得分:1)
或者说你有一个从文件中读取的字符串。我们将此字符串称为“s”
words = filter(lambda x: x!="na", s.split())
除了“na”之外,应该给你所有的字符串
编辑:上面的代码显然没有按照您的意愿执行。
下面的那个应该可以工作
d = s.split()
keys = d[:len(d)/2]
vals = d[len(d)/2:]
w = " ".join(map(lambda (k,v): (k + " " + v) if v!="na" else "", zip(keys, vals)))
print " ".join([" ".join(w.split()[::2]), " ".join(w.split()[1::2])])
答案 3 :(得分:1)
我同意贾斯汀而不是使用拉链是一个好主意。问题是如何将数据放入两个不同的列表中。这是一个应该可行的提案。
reader = open('input.txt')
writer = open('output.txt', 'w')
names, nums = [], []
row = reader.read().split(' ')
x = len(row)/2
for (a, b) in [(n, v) for n, v in zip(row[:x], row[x:]) if v!='na']:
names.append(a)
nums.append(b)
writer.write(' '.join(names))
writer.write(' ')
writer.write(' '.join(nums))
#writer.write(' '.join(names+nums)) is nicer but cause list to be concat
答案 4 :(得分:0)
strlist = 'namenexttolast nameonemore namethelast 0 na 2'.split()
vals = ('0', '1', '2', '3', '4', 'na')
key_list = [s for s in strlist if s not in vals]
val_list = [s for s in strlist if s in vals]
#print [(key_list[i],v) for i, v in enumerate(val_list) if v != 'na']
filtered_keys = [key_list[i] for i, v in enumerate(val_list) if v != 'na']
filtered_vals = [v for v in val_list if v != 'na']
print filtered_keys + filtered_vals
如果您更愿意对val进行分组,则可以创建一个元组列表(注释掉行)
答案 5 :(得分:0)
这是一个只使用迭代器加上一个缓冲区元素的解决方案,没有调用len而没有创建其他中间列表。 (在Python 3中,只需使用map
和zip
,无需从itertools导入imap
和izip
。)
from itertools import izip, imap, ifilter
def iterStartingAt(cond, seq):
it1,it2 = iter(seq),iter(seq)
while not cond(it1.next()):
it2.next()
for item in it2:
yield item
dataline = "namenexttolast nameonemore namethelast 0 na 2"
datalinelist = dataline.split()
valueset = set("0 1 2 3 4 na".split())
print " ".join(imap(" ".join,
izip(*ifilter(lambda (n,v): v != 'na',
izip(iter(datalinelist),
iterStartingAt(lambda s: s in valueset,
datalinelist))))))
打印:
namenexttolast namethelast 0 2