我希望必须将第一个字段(用户名)从File1和第二个字段(密码)输出到第三个文件,该文件在函数期间创建但我无法执行。 :(
文件的格式始终相同:
文件1:
Username:DOB:Firstname:Lastname:::
文件2:
Lastname:Password
我目前的代码:
def merge(f1,f2,f3):
with open(f3, "a") as outputFile:
with open(f1) as usernameFile:
for line in usernameFile:
line = line[:-3]
username = line.split(':')
outputFile.write(username[0])
with open(f2) as passwordFile:
for line in passwordFile:
password = line.split(':')
outputFile.write(password[1])
merge('file1.txt', 'file2.txt', 'output.txt')
我希望File1的用户名和File2的密码用布局写入File3:
Username:Password
Username:Password
Username:Password
任何帮助将不胜感激。 :)
答案 0 :(得分:2)
如果文件的排序相同(即用户在两个文件中的顺序相同),请使用tip in this answer同时迭代这两个文件,而不是在示例中依次迭代。< / p>
from itertools import izip
with open(f3, "a") as outputFile:
for line_from_f1, line_from_f2 in izip(open(f1), open(f2)):
username = line_from_f1.split(':')[0]
password = line_from_f1.split(':')[1]
outputfile.write("%s:%s" % (username, password))
如果文件的排序方式不同,请先从lastname
创建一个包含密钥username
和值file1
的字典。然后使用lastname
中的键password
和值file2
创建第二个字典。然后迭代任一dict的键并打印两个值。
答案 1 :(得分:1)
摘要从文件i / o中提取数据,然后您可以使用不同的提取函数重用merge()
。
import itertools as it
from operator import itemgetter
from contextlib import contextmanager
def extract(foo):
"""Extract username and password, compose and return output string
foo is a tuple or list
returns str
>>> len(foo) == 2
True
"""
username = itemgetter(0)
password = itemgetter(1)
formatstring = '{}:{}\n'
item1, item2 = foo
item1 = item1.strip().split(':')
item2 = item2.strip().split(':')
return formatstring.format(username(item1), password(item2))
@contextmanager
def files_iterator(files):
"""Yields an iterator that produces lines synchronously from each file
Intended to be used with contextlib.contextmanager decorator.
yields an itertools.izip object
files is a list or tuple of file paths - str
"""
files = map(open, files)
try:
yield it.izip(*files)
finally:
for file in files:
file.close()
def merge(in_files,out_file, extract):
"""Create a new file with data extracted from multiple files.
Data is extracted from the same/equivalent line of each file:
i.e. File1Line1, File2Line1, File3Line1
File1Line2, File2Line2, File3Line2
in_files --> list or tuple of str, file paths
out_file --> str, filepath
extract --> function that returns list or tuple of extracted data
returns none
"""
with files_iterator(in_files) as files, open(out_file, 'w') as out:
out.writelines(map(extract, files))
## out.writelines(extract(lines) for lines in files)
merge(['file1.txt', 'file2.txt'], 'file3.txt', extract)
Files_Iterator
是With Statement Context Manager,允许多个同步文件迭代,并确保文件将被关闭。这是阅读的良好开端 - Understanding Python's "with" statement
答案 2 :(得分:1)
这是您需要对代码进行的最小更改才能使其正常工作:
def merge(f1,f2,f3):
with open(f3, "a") as outputFile:
with open(f1) as usernameFile:
for line in usernameFile:
username = line.split(':')[0]
lastname = line.split(':')[3]
outputFile.write(username)
with open(f2) as passwordFile:
for line in passwordFile:
lN, password = line.split(':')
if lN == lastname: outputFile.write(password[1])
merge('file1.txt', 'file2.txt', 'output.txt')
但是,这种方法并不是很好,因为它多次读取文件。我会继续为第二个文件创建一个字典,并以lastname作为键。字典在这些情况下非常有用。可以按照以下方式制作字典:
def makeDict(f2):
dOut = {}
with open(f2) as f:
for l in f:
dOut[ l.split(':')[0] ] = l.split(':')[1]
return dOut
def merge(f1,f2,f3):
pwd = makeDict(f2)
print pwd
with open(f3, "a") as outputFile:
with open(f1) as usernameFile:
for line in usernameFile:
if line.strip() == '': continue
username = line.split(':')[0]
lastname = line.split(':')[3]
if lastname in pwd:
outputFile.write(username + ':' + pwd[lastname] + '\n')
merge('f1.txt', 'f2.txt', 'f3.txt' )
我刚使用这些文件运行以下程序:
f1.txt
Username0:DOB:Firstname:Lastname0:::
Username1:DOB:Firstname:Lastname1:::
Username2:DOB:Firstname:Lastname2:::
Username3:DOB:Firstname:Lastname3:::
f2.txt
Lastname0:Password0
Lastname1:Password1
Lastname2:Password2
Lastname3:Password3
得到了输出:
Username0:Password0
Username1:Password1
Username2:Password2
Username3:Password3
我确实添加了最后一行merge(...)
和另一行用于跳过输入文本中的空白行,但除此之外,一切都应该没问题。如果merge(...
函数未被调用,则不会有任何输出。
答案 3 :(得分:0)
我建议构建两个词典来表示每个文件中的数据,然后根据该结构编写File3:
d1 = {}
with open("File1.txt", 'r') as f:
for line in f:
d1[line.split(':')[3]] = line.split(':')[0]
d2 = {}
with open("File2.txt", 'r') as f:
for line in f:
d2[line.split(':')[0]] = line.split(':')[1]
这将为您提供两个类似的词典:
d1 = {Lastname: Username}
d2 = {Lastname: Password}
然后将其写入文件3,只需运行dicitonary:
的键with open("File3.txt", 'w') as f:
for key in d1:
f.write("{}:{}\n".format(d1[key], d2[key]))
需要注意的一些事项:
如果这些文件没有相同的值,那么您需要为此进行一些处理(如果是这种情况请告诉我,我可以提出一些想法)方式
此方法不保留文件在
代码假定所有行的格式相同。一个更复杂的文件将需要一些代码来处理&#34; odd&#34;线
答案 4 :(得分:0)
如果你在每个文件中有相同排序的行,那么可以避免这种情况。但是,如果它变得更复杂,那么你应该使用pandas。使用pandas,您基本上可以进行连接,因此,无论每个文件中的行如何排序,这都可以。它也非常简洁。
import pandas as pd
df1 = pd.read_csv(f1, sep=':', header=None).ix[:,[0,3]]
df1.columns = ['username', 'lastname']
df2 = pd.read_csv(f2, sep=':', header=None)
df2.columns = ['lastname', 'password']
df3 = pd.merge(df1, df2).ix[:,['username','password']]
df3.to_csv(f3, header=False, index=False, sep=':')
请注意,您还可以选择执行外连接。如果由于某种原因,文件中存在没有密码的用户名,反之亦然,这很有用。
答案 5 :(得分:0)
这非常接近。确保输入文件末尾没有空白行,或者在阅读时添加代码以跳过空白行。
#!/usr/bin/env python
"""
File 1:
Username:DOB:Firstname:Lastname:::
File2:
Lastname:Password
File3:
Username:Password
"""
def merge(f1,f2,f3):
username_lastname = {}
with open(f3, "a") as outputFile:
with open(f1) as usernameFile:
for line in usernameFile:
user = line.strip().split(':')
print user
username_lastname[user[3]] = user[0] # dict with Lastname as key, Username as value
print username_lastname
with open(f2) as passwordFile:
for line in passwordFile:
lastname_password = line.strip().split(':')
print lastname_password
password = lastname_password[1]
username = username_lastname[lastname_password[0]]
print username, password
out_line = "%s:%s\n" % (username, password)
outputFile.write(out_line)
outputFile.close()
merge('f1.txt', 'f2.txt', 'output.txt')
f1:
Username1:DOB:Firstname:Lastname1:::
Username2:DOB:Firstname:Lastname2:::
Username3:DOB:Firstname:Lastname3:::
f2:
Lastname1:Password1
Lastname2:Password2
Lastname3:Password3
f3:
Username1:Password1
Username2:Password2
Username3:Password3