我在由空格分隔的单行上有一个包含名称和值的大文件:
name1 name2 name3....
在长长的名称列表之后是与名称对应的值列表。这些值可以是 0-4 或 na。我想要做的是合并数据文件并在值为na
.
例如,这个文件中的最后一行名称是这样的:
namenexttolast nameonemore namethelast 0 na 2
我想要以下输出:
namenexttolast namethelast 0 2
我将如何使用 Python 做到这一点?
我在由空格分隔的单行上有一个包含名称和值的大文件:
name1 name2 name3....
在长长的名称列表之后是与名称对应的值列表。这些值可以是 0-4 或 na。我想要做的是合并数据文件并在值为na
.
例如,这个文件中的最后一行名称是这样的:
namenexttolast nameonemore namethelast 0 na 2
我想要以下输出:
namenexttolast namethelast 0 2
我将如何使用 Python 做到这一点?
假设您将名称读入一个列表,然后将值读入另一个列表。一旦你有一个names
和values
列表,你可以做类似的事情:
result = [n for n, v in zip(names, values) if v != 'na']
result
现在是值不是“na”的所有名称的列表。
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)
更新
根据 Paul 的建议进行了小幅改进。我确信列表推导是相当不符合 Python 的,因为它利用了 return 的事实,因此两个表达式都list.append
将被评估,并且将构造一个值列表并立即丢弃。None
append
None
或者说你有一个从文件中读取的字符串。让我们将此字符串称为“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])])
我同意贾斯汀的观点,而不是使用 zip 是个好主意。问题是如何将数据放入两个不同的列表中。这是一个应该可以正常工作的建议。
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
这是一个仅使用迭代器和单个缓冲区元素的解决方案,没有调用 len 也没有创建其他中间列表。(在 Python 3 中,只需使用map
and 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
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 进行分组,则可以创建一个元组列表(注释掉的行)