在Python中合并两个不同长度的文件

在Python中合并两个不同长度的文件,python,Python,我有两个列数相同但行数不同的文件。一个文件是时间戳列表和单词列表,第二个文件是时间戳列表,每个单词中都有一个声音列表,即: 9640 12783 she 12783 17103 had ... 以及: 我想合并这两个文件并创建一个条目列表,其中单词作为一个值,拼音作为另一个值,即: [['she', 'sh iy'] ['had', 'hv ae dcl d'] ... 我是一个完整的Python(和编程)noob,但我最初的想法是通过在第二个文件中搜索第一个文件中的第二个字段,然后将

我有两个列数相同但行数不同的文件。一个文件是时间戳列表和单词列表,第二个文件是时间戳列表,每个单词中都有一个声音列表,即:

9640 12783 she
12783 17103 had
...
以及:

我想合并这两个文件并创建一个条目列表,其中单词作为一个值,拼音作为另一个值,即:

[['she', 'sh iy']
 ['had', 'hv ae dcl d']
  ...
我是一个完整的Python(和编程)noob,但我最初的想法是通过在第二个文件中搜索第一个文件中的第二个字段,然后将它们附加到一个列表中。我试着这样做:

word=open('SA1.WRD','r')
电话=打开('SA1.PHN','r')
word_phone=[]
对于word.readlines()中的行:
words=line.split()
单词=单词[2]
word\u phone.append(word)
对于电话线输入。readlines():
phones=line.split()
电话=电话[2]

如果int(phones[1])这是一项主要问题是将声音与单词匹配的任务。幸运的是,这是很容易做到的,因为我们可以简单地把所有的声音,直到他们匹配的话结束时间

为此,我们必须构造一个
takeuntil()
函数-
itertools.takewhile()
(我的原始解决方案)不幸地需要一个额外的值,因此这是最好的解决方案

def takeuntil(iterable, stop):
    for x in iterable:
        yield x
        if x[1] == stop:
            break

with open("SA1.WRD") as unsplit_words, open("SA1.PHN") as unsplit_sounds:
    sounds = (line.split() for line in unsplit_sounds)
    words = (line.split() for line in unsplit_words)
    output = [
        (word, " ".join(sound for _, _, sound in takeuntil(sounds, stop)))
        for start, stop, word in words
    ]

print(output)
给了我们:

[('she', 'sh iy'), ('had', 'hv ae dcl d')]
此代码用于可读性和关闭文件(即使在异常情况下)。它还大量使用了

您的代码中有一些不好的模式。使用
open()
而不使用
with
语句是一个坏主意,并且不需要使用
readlines()
(直接在文件上循环-它很懒惰,因此在大多数情况下效率更高,更不用说读起来更好,打字更少)

那么这是如何工作的呢?让我们浏览一下:

首先,我们打开两个文件进行读取,并插入快速生成器表达式来分割文件中的行

接下来是一个怪物列表。我们要做的是从
sounds
iterable中提取声音,直到到达属于我们所处单词的最后一个声音,然后移动到下一个单词,返回单词和相关声音列表。然后我们使用
str.join()
将声音连接成一个字符串

如果您在理解思维过程方面有困难,那么这里有一个扩展版本,它以同样的方式工作,尽管由于python端循环(生成器和列表理解使上述过程更快),效率要低得多:


如果这是家庭作业,请添加
家庭作业
标签。这实际上是一个更大的研究计划(课外)的一部分,但感谢您的通知。好的。对不起,我有点讨厌和怀疑:-)。哇,我想你应该把“一行”的格式设置得好一点:)除此之外,这正是我要建议的,所以+1@NiklasB. 是的,我只是在清理它并添加解释。我认为这里缺少了
iy
,因为
takewhile
扔掉了条件为false的项目。这就成功了。再次感谢您的帮助和解释。这对我来说是对StackOverflow的一个很好的介绍。@UW语言学家:也祝你黑客愉快:)
phns = []
wrds = []
for root, dir, files in os.walk(sys.argv[1]):
    wrds = wrds + [ os.path.join( root, f ) for f in files if f.endswith( '.WRD' ) ]
    phns = phns + [ os.path.join( root, f ) for f in files if f.endswith( '.PHN' ) ]
phns.sort()
wrds.sort()
files = (zip(wrds,phns))

#OPEN THE WORD AND PHONE FILES, COMPARE THEM
output = []
for file in files:
    with open( file[0] ) as unsplit_words, open( file[1] ) as unsplit_sounds:
        sounds = (line.split() for line in unsplit_sounds)
        words = (line.split() for line in unsplit_words)
        output = output +  [
          (word, " ".join(sound for _, _, sound in
                    takeuntil(sounds, stop)))
                for start, stop, word in words
            ]
[('she', 'sh iy', 'directory', 'subdirectory'), ('had', 'hv ae dcl d', 'directory', subdirectory')]
def takeuntil(iterable, stop):
    for x in iterable:
        yield x
        if x[1] == stop:
            break

with open("SA1.WRD") as unsplit_words, open("SA1.PHN") as unsplit_sounds:
    sounds = (line.split() for line in unsplit_sounds)
    words = (line.split() for line in unsplit_words)
    output = [
        (word, " ".join(sound for _, _, sound in takeuntil(sounds, stop)))
        for start, stop, word in words
    ]

print(output)
[('she', 'sh iy'), ('had', 'hv ae dcl d')]
with open("SA1.WRD") as words, open("SA1.PHN") as sounds:
    output = []
    current = []
    for line in words:
        start, stop, word = line.split()
        for sound_line in sounds:
            sound_start, sound_stop, sound = sound_line.split()
            current.append(sound)
            if sound_stop == stop:
                break
        output.append((word, " ".join(current)))
        current = []

print(output)