что лучший способ состоит в том, чтобы преобразовать рубиновый хеш в массив

Вопрос плохо определен, но если предположить, что OP хочет получить результат, показанный в примере DataFrame (то есть не только последняя строка каким-то образом украшена именем файла, но все строки), здесь есть способ добиться этого. Для этого примера у нас есть только два файла: file1.txt содержит две строки: «a» и «b», file2.txt содержит одну строку: «c».

Мы пишем средство чтения файлов, которое возвращает список списков: каждый подсписок содержит имя файла и строку.

import glob

def get_file(filename):
    with open(filename) as f:
        return [[filename, line.rstrip('\n')] for line in f]

Попробуйте:

m = map(get_file, glob.glob('file*.txt'))
list(m)

Out[]:
[[['file2.txt', 'c']], [['file1.txt', 'a'], ['file1.txt', 'b']]]

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

def flatten(m):
    return [k for sublist in m for k in sublist]

m = map(get_file, sorted(glob.glob('file*.txt')))
flatten(m)

Out[]:
[['file1.txt', 'a'], ['file1.txt', 'b'], ['file2.txt', 'c']]

Теперь иногда полезно иметь номер строки (например, если мы собираемся поместить эти данные в DataFrame и выполнить дальнейшую сортировку и аналитику). Наш читатель становится:

def get_file(filename):
    with open(filename) as f:
        return [[filename, lineno, line.rstrip('\n')] for lineno, line in enumerate(f, start=1)]

m = map(get_file, sorted(glob.glob('file*.txt')))
out = pd.DataFrame(flatten(m), columns=['filename', 'lineno', 'line'])
out

Out[]:
    filename  lineno line
0  file1.txt       1    a
1  file1.txt       2    b
2  file2.txt       1    c

Обратите внимание, что вышеприведенный map прекрасно подходит для многопоточного чтения, если у нас есть большое количество файлов:

from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(max_workers=4) as pool:
    m = pool.map(get_file, sorted(glob.glob('file*.txt')))
    out = pd.DataFrame(flatten(m), columns=['filename', 'lineno', 'line'])
out

Out[]:
    filename  lineno line
0  file1.txt       1    a
1  file1.txt       2    b
2  file2.txt       1    c
5
задан epochwolf 16 April 2009 в 17:00
поделиться

2 ответа

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

def array_from_hash(h)
  return h unless h.is_a? Hash

  all_numbers = h.keys.all? { |k| k.to_i.to_s == k }
  if all_numbers
    h.keys.sort_by{ |k| k.to_i }.map{ |i| array_from_hash(h[i]) }
  else
    h.each do |k, v|
      h[k] = array_from_hash(v)
    end
  end
end
8
ответ дан 13 December 2019 в 05:42
поделиться

Если мы сможем Предположим, что все ключи на самом деле являются строками, которые конвертируются чисто в целые числа, должно работать следующее:

# "hash" here refers to the main hash in your example, since you didn't name it
stuff_hash = hash["stuff"]
hash["stuff"] = stuff_hash.keys.sort_by {|key| key.to_i}.map {|key| stuff_hash[key]}
4
ответ дан 13 December 2019 в 05:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: