2013-05-28 3 views
2

У меня очень большой текстовый файл, содержащий статистику хоккея.разобрать файл, чтобы получить 10 лучших игроков.

мне нужны две вещи из каждой строки:.

  1. имя игрока
  2. точки (первый набор чисел)

И я хочу, чтобы вернуться в топ-10 список.

Ниже приведен образец текстового файла, но он продолжается намного дольше.

html_log:Bob 1217.1 1.75 696:48 1 5 38 6 109 61 14:42 633 223 25 435:36 182 34 0.55  
html_log:Steve 485.5 1.26 385:18 7 12 -1 28 172 218 16:04 839 94 101 143:18 44 15 -0.03 
html_log:Jim 1153.3 1.84 625:54 1 2 71 3 2 10 7:58 499 3 5 616:36 241 36 1.13 

-repeats с большим количеством игроков и статистика (без перевода строки)

мне нужно получить имя игрока в этом случае текст после «html_log» тега я также нужен первый набор чисел , и для вывода верхнего списка 10 нужно выводить.

Оптимальный результат был бы выход

- >>

Bob 1217.1 
Jim 1153.3 
Steve 485.5 

+ остальные пользователи в текстовом файле, и их рейтинг, от высшего к низшему. или только 10 лучших из текстового файла.

+2

Что вы пробовали до сих пор? Какую часть вы застряли? Разбор файла должен быть простым с помощью нескольких вызовов «split» или регулярного выражения. Получение 10 лучших из любого итерабельного легко с помощью 'heapq.nlargest'. Если вы правильно настроите свой код, этот итерабельный может быть итератором, который вы кормите, когда идете вперед. – abarnert

+0

Насколько велика большая? Килобайты, мегабайты, гигабайты? – mvp

+0

Я согласен с @abarnert.разбор этого файла довольно прост. – IcyFlame

ответ

6

Просто сложите его на мелкие кусочки, каждый из которых прост.

На английском языке: для каждой строки в файле вы хотите получить первые два значения, и вы хотите разбить первое значение после двоеточия, и вы хотите обработать второе значение как число. Затем вы хотите отслеживать первые 10 пар, упорядоченных по этому второму значению.

В Python:

with open('large_file.txt') as f: 
    pairs = (line.split()[:2] for line in f) 
    processed_pairs = ((pair[0].split(':')[1], float(pair[1])) for pair in pairs) 
    top_10_pairs = heapq.nlargest(10, processed_pairs, key=operator.itemgetter(1)) 

Теперь у Вас есть list из name, score пар, что легко распечатать:

for name, score in top_10_pairs: 
    print('{} {}'.format(name, score)) 

Независимо от того, насколько большой файл, это не будет содержать более 10 обработанных пар (плюс буфер чтения и некоторые другие базовые элементы) в памяти за раз, потому что мы просто шаг за шагом превращаем итератор с файлами (файлом) в другие итераторы и кормлением что в heapq.nlargest, w hich только держит верхнюю часть n вокруг.

2
dict(line.split()[:2] for line in 
    [line.split(":")[1] for line in data.split("\n")]) 
# {'Bob': '1217.1', 'Jim': '1153.3', 'Steve': '485.5'} 
+1

Это не сортирует результаты или не попадает в топ 10. Хотя вы можете добавить 'sorted (d.items(), key = lambda pair: float (пара [1]), reverseed = True)' или что-то, это потребует сохранения (двух копий) всего этого в памяти и выполнения O (N log N) сортировки, ни один из которых не нужен здесь. – abarnert

+0

@abarnert Вы правы. –

-3

Следующий код делает именно то, что вы хотите сделать:

Филин = открытый («файл», «г»)

d = {} 

for i in filin: 

    startName = i.find('html_log:') + len('html_log:') 

    endName = i.find(' ',startName) 

    name = i[startName:endName] 

    startPoint = endName + 1 

    endPoint = i.find(' ',startPoint) 

    points = i[startPoint:endPoint] 

    d[points] = name 

d.keys().sort() 

counter = 0 ##to make sure that we print only the top 10 

filin.close() 

for key in d.keys(): 


    print d[key],' ',key 

    counter += 1 

    if counter == 10: 

     break 
+1

Если строки не все начинаются с 'html_log:', это будет сделано не так (и если они _do_ все начинаются с 'html_log:', это не нужно). И я бы дал 50/50 шансов, что у вас есть, по крайней мере, одна ошибка «один за другим» где-то там. Именно поэтому у нас есть такие функции, как 'split', поэтому нам не нужно иметь дело с этим. – abarnert

+2

Кроме того, вы сортируете по строковому значению 'points', поэтому' 9' будет считаться больше, чем '1000'. И вам нужно иметь достаточно памяти для чтения всего файла в памяти таким образом, даже если вы хотите только 10 лучших. И вы никогда не закрываете файл. И использование «счетчика» с ручным приращением в цикле глупо; просто используйте 'enumerate'. Но почему даже беспокоиться, когда вы можете просто нарезать его? – abarnert

+0

@abarnert: это казалось очень интуитивным способом сделать это. И синтаксический анализ файлов должен быть больше связан с разбором файла в руке, а не с использованием всех видов функций! Хотя я согласен с вами в сравнении со строкой! моя вина! – IcyFlame

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