Что означают заголовки при добавлении CSV::Row в CSV::Table в Ruby 1.9?

Я пытаюсь добавить строку в CSV::Table в Ruby 1.9 (вопросы также относятся к FasterCSV в Ruby 1.8). Если порядок столбцов в новой строке отличается от порядка в таблице, элементы добавляются не в те столбцы, даже если заголовки указаны правильно. Похоже, что заголовки в новой строке игнорируются.

require 'csv'

first_row = CSV::Row.new(["h1","h2","h3"],[1,2,3])
second_row = CSV::Row.new(["h2","h1","h3"],[2,1,3]) # note the change in order
table = CSV::Table.new([first_row])
table << second_row
puts table.to_s

Вывод:

h1,h2,h3
1,2,3
2,1,3

Но поскольку я указываю заголовки явно, я ожидаю, что CSV сопоставит заголовки новой строки с заголовками таблицы и выдаст следующий вывод:

h1,h2,h3
1,2,3
1,2,3

Любые объяснения? Могу ли я что-то с этим сделать, кроме как самостоятельно изменить порядок столбцов перед созданием новой строки?


person Stefan    schedule 18.07.2011    source источник


Ответы (2)


Объяснение в исходном коде CSV::Table#to_csv.

Я новичок в Ruby, но попробуйте мой патч:

--- csv.rb.old  2011-07-18 23:24:38.184913108 +0600
+++ csv.rb  2011-07-18 23:23:54.972802099 +0600
@@ -836,7 +836,7 @@
         if row.header_row?
           rows
         else
-            rows + [row.fields.to_csv(options)]
+            rows + [row.fields(*headers).to_csv(options)]
         end
       end.join
     end

Вывод:

h1,h2,h3
1,2,3
1,2,3
person scuawn    schedule 18.07.2011
comment
Большое спасибо, scuawn, ваш патч отлично работает. См. также мой комментарий к ответу Давида. - person Stefan; 19.07.2011

Как упоминалось в ответ scuawn, метод CSV::Table#to_csv работает не так, как вы ожидаете.

Однако данные в CSV::Table размещаются в нужных столбцах! Основываясь на вашем примере, вы можете видеть, что это правда:

irb(main):1:0> table.entries
=> [#<CSV::Row "h1":1 "h2":2 "h3":3>, #<CSV::Row "h2":2 "h1":1 "h3":3>]
irb(main):2:0> table.headers
=> ["h1", "h2", "h3"]
irb(main):3:0> table.values_at(*table.headers)
=> [[1, 2, 3], [1, 2, 3]]
person David Unric    schedule 18.07.2011
comment
Спасибо, это было полезно. Однако теперь я думаю, что CSV::Table — это просто набор CSV::Rows без строгого понятия столбцов. Правильный порядок в столбцах происходит, когда вы вызываете values_at(). Если вы используете table.by_col[0] для получения первого столбца, вы все равно получите [1,2] вместо [1,1]. - person Stefan; 19.07.2011
comment
Я согласен, что есть недостаток в коде #to_csv или даже в методе #‹‹, который мог бы сразу сохранять строки, упорядоченные по заголовку. - person David Unric; 19.07.2011