0

我在由空格分隔的单行上有一个包含名称和值的大文件:

name1 name2 name3....

在长长的名称列表之后是​​与名称对应的值列表。这些值可以是 0-4 或 na。我想要做的是合并数据文件并在值为na.

例如,这个文件中的最后一行名称是这样的:

namenexttolast nameonemore namethelast 0 na 2

我想要以下输出:

namenexttolast namethelast 0 2

我将如何使用 Python 做到这一点?

4

6 回答 6

5

假设您将名称读入一个列表,然后将值读入另一个列表。一旦你有一个namesvalues列表,你可以做类似的事情:

result = [n for n, v in zip(names, values) if v != 'na']

result现在是值不是“na”的所有名称的列表。

于 2010-07-28T19:19:33.047 回答
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)

更新

根据 Paul 的建议进行了小幅改进。我确信列表推导是相当不符合 Python 的,因为它利用了 return 的事实,因此两个表达式都list.append将被评估,并且将构造一个值列表并立即丢弃。NoneappendNone

于 2010-07-28T19:58:33.007 回答
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])])
于 2010-07-28T19:58:15.170 回答
1

我同意贾斯汀的观点,而不是使用 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
于 2010-07-28T20:02:04.883 回答
0

这是一个仅使用迭代器和单个缓冲区元素的解决方案,没有调用 len 也没有创​​建其他中间列表。(在 Python 3 中,只需使用mapand 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
于 2010-07-29T07:09:53.210 回答
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 进行分组,则可以创建一个元组列表(注释掉的行)

于 2010-07-28T20:32:02.793 回答