2012-05-13 3 views
2

У меня есть два файла с одинаковым количеством столбцов, но с другим количеством строк. Один файл представляет собой список временных меток и список слов, второй файл представляет собой список временных меток со списком звуков в каждом из слов, то есть ,:Объединить два файла разной длины в Python

9640 12783 she 
12783 17103 had 
... 

и:

9640 11240 sh 
11240 12783 iy 
12783 14078 hv 
14078 16157 ae 
16157 16880 dcl 
16880 17103 d 
... 

Я хочу, чтобы объединить эти два файла и создать список записей со словами в качестве одного значения, и фонетической транскрипции как другой, то есть ,:

[['she', 'sh iy'] 
['had', 'hv ae dcl d'] 
    ... 

Я полный Python (и программирование) нуб , но мой Первоначальная идея состояла в том, чтобы сделать это, выполнив поиск второго файла для второго поля в первом файле, а затем добавив его в список. Я пытался делать это так:

word = open('SA1.WRD','r') 
phone = open('SA1.PHN','r') 
word_phone = [] 

for line in word.readlines(): 
    words = line.split() 
    word = words[2] 
    word_phone.append(word) 

for line in phone.readlines(): 
    phones = line.split() 
    phone = phones[2] 
    if int(phones[1]) <= int(words[1]): 
     word_phone.append(phone) 

print word_phone 

Это выход:

['she', 'had', 'your', 'dark', 'suit', 'in', 'greasy', 'wash', 'water', 'all', 'year', 'sh', 'iy', 'hv', 'ae', 'dcl', 'd', 'y', 'er', 'dcl', 'd', 'aa', 'r', 'kcl', 'k', 's', 'uw', 'dx', 'ih', 'ng', 'gcl', 'g', 'r', 'iy', 's', 'iy', 'w', 'aa', 'sh', 'epi', 'w', 'aa', 'dx', 'er', 'q', 'ao', 'l', 'y', 'iy', 'axr'] 

Как я уже сказал, я в общей сложности нуб, и некоторые предложения были бы очень полезны.

Обновление: Я хотел бы пересмотреть этот вопрос, если это возможно. Я изменил код Lattyware, чтобы работать на каталоге:

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')] 

Я полагал, что я мог бы я мог разделить пути, а затем заархивировать списки вместе, но 53 000 общих элементов в списке выведенных выше выходов, но обрабатывается только 6300 пар файлов.

+0

Если это домашнее задание, добавьте тег 'homework'. –

+0

Это на самом деле часть более крупной исследовательской программы (вне класса), но спасибо за уведомление. – UWLinguist

+0

ОК. Извините за неприятность и подозрительность :-). –

ответ

3

Это задача, в которой основная проблема заключается в совпадении звуков со словами. К счастью, это легко сделать, поскольку мы можем просто взять все звуки, пока они не совпадут с временем окончания слов.

Для этого мы должны построить функцию 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')] 

Этот код использует the with statement для удобства чтения и закрытия файлов (даже исключения). Он также очень часто использует list comprehensions and generator expressions.

В коде есть некоторые плохие шаблоны. Ваше использование open() без инструкции with - это плохая идея, и использование readlines() не требуется (цикл непосредственно над файлом - он ленив и, следовательно, гораздо эффективнее в большинстве случаев, не говоря уже о том, что лучше читать и не печатать).

Как это работает?Пройдём через него:

Сначала мы открываем оба наших файла для чтения и генерируем быстрые выражения генератора для разделения строк в файлах.

Далее идет бит понимания монстра. Что мы делаем в этом случае, это звуки из нашего sounds итерации, пока мы не достигнем последнего звука, принадлежащего слову, на котором мы находимся, затем переходим к следующему слову, возвращая слово и список связанных звуков. Затем мы используем str.join() для объединения звуков в одну строку.

Если у вас есть проблемы с пониманием мыслительного процесса, то вот расширенная версия, которая работает точно так же, хотя и гораздо менее эффективно благодаря питоной стороне петлям (генераторы и списочные делают выше гораздо быстрее):

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) 
+0

Ничего себе, я думаю, вы должны отформатировать этот «один лайнер» немного лучше :) Кроме этого, это в значительной степени то, что я собирался предложить, поэтому +1 –

+0

@NiklasB. Да, я просто убираю его и добавляю объяснения. –

+0

Я думаю, что 'iy' отсутствует здесь, из-за' takewhile', отбрасывающего элемент, на котором условие ложно. –

Смежные вопросы