2013-10-08 5 views
1

Я пытаюсь выполнить эту задачу весь день, и я действительно хочу научиться делать это с помощью Python. Я хочу взять два файла с разделителями табуляции, один с идентификатором, а другой с тем же идентификатором и некоторым описанием. Я могу легко объединить эти файлы в поле shared ID с unix join, но для этого мне нужно отсортировать оба, и я хочу сохранить порядок первого файла.Python: Сортировка двух файлов на основе порядка

Ive пробовал код ниже, и мой метод заключался в том, чтобы попытаться добавить вещи в кортеж, поскольку, насколько я понимаю, они будут соблюдать порядок, когда вы добавляете к нему. Тем не менее, я не мог заставить все работать. Может ли кто-нибудь помочь?

Примеры файлов:

file1 -> 
111889 
1437390 
123 
27998 
2525778 
12 
1345 

file2 -> 
2525778'\t'item778 
1345'\t'item110 
123'\t'item1000 
12'\t'item8889 
111889'\t'item1111 
1437390'\t'item222 
27998'\t'item12 

output -> 
111889'\t'item1111 
1437390'\t'item222 
123'\t'item1000 
27998'\t'item12 
2525778'\t'item778 
12'\t'item8889 
1345'\t'item110 

Это то, что я до сих пор:

import sys 

add_list =() 

with open(sys.argv[1], 'rb') as file1, open(sys.argv[2], 'rb') as file2: 
     for line2 in file2: 
       f1, f2, f3 = line2.split('\t') 
       #print f1, f2, f3 
       for row in file1: 
         #print row 
         if row != f1: 
           break 
         else: 
           add_list.append(f1,f2,'\n') 
           break 
+0

Насколько велики вы ожидаете, что ваши файлы будут? Можно ли предположить, что все они могут быть прочитаны в памяти одновременно? Если нет, то для этого потребуются более сложные внешние методы ... – lightalchemist

+0

Кортеж неизменен (не может быть изменен), и вы не можете добавить его. Вы хотите использовать список, '[]'. Кроме того, '.append()' принимает только один элемент. – monkut

+0

Действительно, ваша алгоритмическая сложность - O (n^2), что означает, что для входного набора из n элементов он обрабатывает все элементы n^2 раза. Слияние, особенно если это можно сделать в памяти, это сложность O (n) (с использованием словарного подхода). Для 1000 предметов это означает, что оно на 3 порядка быстрее. –

ответ

3

Ключ использовать Python словари, они идеально подходят для этой задачи ...

Здесь является полным ответом:

import sys 

# Each id is mapped to its item name 
# (split() splits at whitespaces (including tabulation and newline), with no empty output strings): 
items = dict(line.split() for line in open(sys.argv[2])) # Inspired by mgilson's answer 

with open(sys.argv[1]) as ids: 
    for line in ids: 
     id = line.rstrip() # newline removed 
     print '{}\t{}'.format(id, items[id]) 

Вот результат:

% python out.py file1.txt file2.txt 
111889 item1111 
1437390 item222 
123  item1000 
27998 item12 
2525778 item778 
12  item8889 
1345 item110 

PS: Обратите внимание, что я не открывать файлы в режиме rb, так как нет необходимости хранить оригиналы новой строки байтов, здесь, так как мы избавимся завершающих переводы строк ,

+0

Thats great thanks. По какой-то причине я думал, что словари все равно оставят меня без функции сортировки по первому файлу. – gammyknee

+2

Словари действительно не имеют определенного порядка. Однако для вывода идентификаторы выбираются из вашего файла 'file1' один за другим: это то, откуда происходит заказ. Словарь используется только для привязки идентификатора к элементу. – EOL

1

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

with open('file2') as fin: 
    d = dict(x.split(None, 1) for x in fin) 

Тогда я использовал бы первый файл для построения вывода, чтобы из словаря:

with open('file1') as fin, open('output', 'w') as fout: 
    for line in fin: 
     key = line.strip() 
     fout.write('{key}\t{value}\n'.format(key=key, value=d[key]) 
+0

Хорошее создание словаря! 'strip()' будет лучше, чем 'rstrip()', так как это более надежный (но не полностью необходимый здесь, однако), но более важный, более явный (перенос новой строки). С другой стороны, ограничение количества разделов в 'split()' на самом деле не требуется, так как входной файл имеет два столбца, а если нет, то элементы имеют вкладки, которые не должны хорошо воспроизводиться с выходом с вкладками в любом случае ... – EOL

+0

@EOL - Да. Лучший вариант здесь действительно зависит от ограничений на текст в файле.Я думаю, что я собираюсь сделать предположение, что пробелы, отличные от новой строки, не являются существенными. Если это правда, я думаю, что 'x.split (None, 1)' в сочетании с 'line.strip' лучше всего, но может быть, что явное расщепление на' \ t' лучше, если id может иметь пробелы в нем. Это было бы смешно. – mgilson

+0

+1 для 'dict()', очень ясно. :) – EOL

0
out = {} 
with open(sys.argv[1], 'rb') as file1, open(sys.argv[2], 'rb') as file2: 
    d2 = {} 
    for line in file2: 
     (key, val) = line.split('\t') 
     d2[key] = val 
    lines = file1.readlines() 
    out = { x:d2[x] for x in lines } 

Я не уверен в вашей сортировке.

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