объединить несколько файлов CSV perl

Как я могу объединить несколько файлов CSV в Perl?

Например, у меня есть файл 1 Packet1.csv, который выглядит так:

#type, number, info, availability
computer, t.100, pentium 2, yes
computer, t.1000, pentium 3, yes
computer, t.2000, pentium 4, no
computer, t.3000, pentium 5, yes

и файл 2 Packet2.csv, который выглядит так:

#type, number, info, availability
computer, t.100, pentium 2, yes
computer, t.1000, pentium 3, no
computer, t.2000, pentium 4, no
computer, t.4000, pentium 6, no

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

#type, number, info, **Packet1** availability, **Packet2** availability
computer, t.100, pentium 2, yes, yes
computer, t.1000, pentium 3, yes, no
computer, t.2000, pentium 4, no, no
computer, t.3000, pentium 5, yes
computer, t.4000, pentium 6, no

person TheBlackCorsair    schedule 28.11.2012    source источник
comment
Сколько у вас данных? Можно ли загрузить все в память? Всегда ли ваш ввод сортируется, как в примере?   -  person pmakholm    schedule 28.11.2012
comment
@Tim N Я пытался использовать многомерные хэши   -  person TheBlackCorsair    schedule 28.11.2012
comment
@TheBlackCorsair Почему это не сработало?   -  person Tim    schedule 28.11.2012
comment
См. также stackoverflow.com/questions/13588129/, который, похоже, работает над тем же проектом, что и вы...   -  person MattLBeck    schedule 28.11.2012
comment
@pmakholm Да, ввод обычно сортируется таким образом. Иногда это может быть больше элементов. Первые три столбца (тип, номер, информация) фиксированы, и меняется только доступность. На данный момент у меня есть 18 таких пакетов, но в будущем это может измениться   -  person TheBlackCorsair    schedule 28.11.2012
comment
@simbabque нет, я работаю над этим, и я обновлю   -  person TheBlackCorsair    schedule 28.11.2012


Ответы (2)


Возвращаясь к вашей попытке многомерного хеширования: Hash of hashes perl, вам нужно будет изменить структура данных, которую вы используете для хранения нескольких записей определенного элемента.

CSV можно интуитивно считывать в хеш с двумя уровнями. Строки csv могут быть хэшированы по их идентификаторам (в этом случае я предполагаю, что идентификаторы - это числа «t.100», «t.1000» и т. д.), а значения каждой строки могут быть сохранены в хэше второго уровня, используя строки заголовка в качестве его ключей. Это будет выглядеть примерно так, если вы просматривали структуру с помощью Data::Dumper:

$VAR1 = {
          't.1000' => {
                        'info' => 'pentium 3',
                        'availability' => 'yes',
                        'type' => 'computer'
                      },
          't.100' => {
                       'info' => 'pentium 2',
                       'availability' => 'yes',
                       'type' => 'computer'
                     }
        };

Является ли «число» также ключом для каждого «хэша строки», зависит от вас, в зависимости от того, насколько это может быть полезно (обычно вы уже знаете ключ для строки, чтобы получить к ней доступ).

Эта структура данных подойдет для хранения одного CSV-файла. Однако нам нужно добавить дополнительный уровень сложности, чтобы справиться с объединением нескольких CSV так, как вы описываете. Например, чтобы отслеживать файлы, в которых появляется определенный идентификатор, мы можем сохранить третий хеш как значение ключа «доступность», поскольку это значение, которое изменяется между записями одного и того же «числа»:

'availability' => {
          'Packet1' => 'yes',
          'Packet2' => 'no'
        };

После того, как все файлы будут прочитаны в эту структуру, печать окончательного CSV-файла представляет собой процесс циклического перебора ключей внешнего хэша и «присоединения» ключей строки для каждой строки в правильном порядке. Хэш «Пакет» также можно зациклить, чтобы получить все значения «доступности», и их можно добавить в конец каждой строки.

Я надеюсь, что это поможет вам понять один из возможных способов работы с такого рода данными. Вы можете спросить о конкретных частях реализации, если они вам кажутся трудными, и я буду рад подробно рассказать.

person MattLBeck    schedule 28.11.2012
comment
спасибо @kikumbob я попробую и дам тебе знать - person TheBlackCorsair; 28.11.2012

  • Как определить, какой компьютер какой? Вы зависите от первых трех полей в качестве идентификации компьютера?
  • Что делать, если первое поле не computer?
  • Что произойдет, если два файла не совпадают с типом компьютера?

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

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

Например, предположим, что у вас есть хэш с именем %computer, который определяется вторым полем:

my %system;

$system{t.100} = {}    #This is a hash of hashes
$system{t.100}->{INFO} = "pentium 2";
$system{t.100}->{TYPE} = "computer";
$computer{t.100}->{AVAILABLITY} = []  #Storing an array in this hash entry (hash of hashes of arrays)
$computer{t.100}->{AVAILABILITY}->[0] = "yes";
$computer{5.100}->{AVAILABILITY}->[1] = "yes";

Вы также можете использовать push и pop, разыменовав массив:

push @{ $computer{t.100}->{AVAILABILITY} }, "yes";

Обратите внимание, что я окружил ссылку на массив $computer{t.100}->{AVAILABILITY} @{...}, и она превращается из ссылки на массив обратно в массив.

Надеюсь, это то, о чем вы спрашиваете. Вы можете использовать модуль Text::CSV для анализа файла CSV, но если формат не слишком дурацкая, вы, вероятно, могли бы просто использовать команду split.

person David W.    schedule 28.11.2012