2012-05-23 4 views
1

Je n'arrive pas à comprendre comment convertir un hachage en un tableau multidimensionnel. J'ai le hachage suivant produit à partir roo après avoir lu une feuille de calcul Excel:Comment convertir un hachage en tableau ou en tableau?

{[1, 1]=>"string-1", [1, 2]=>"string-2", [1, 3]=>"string-3", [1, 4]=>"string-4", 
[1, 5]=>"string-5", [1, 6]=>"string-6", [1, 7]=>"string-7", [2, 1]=>"string-1", 
[2, 2]=>"string-2", [2, 3]=>numeric-1, [2, 4]=>numeric-2, [2, 5]=>"string-3", 
[2, 6]=>"string-4", [2, 7]=>numeric-3, [3, 1]=>"string-1", [3, 2]=>"string-2", 
[3, 3]=>numeric-1, [3, 4]=>numeric-2, [3, 5]=>"string-3", [3, 6]=>"string-4", 
[3, 7]=>numeric-3, ... etc} 

je dois convertir en:

[["string-1", "string-2", "string-3", "string-4", "string-5", "string-6", "string-7"], 
["string-1", "string-2", numeric-1, numeric-2, "string-3", "string-4", numeric-3], 
["string-1", "string-2", numeric-1, numeric-2, "string-3", "string-4", numeric-3], 
... etc] 

J'ai essayé les suivants, mais il est tout simplement la copie tout en un seul tableau, plutôt que les réseaux intégrés:

2.upto(input.last_row).each do |row| 
    ((input.first_column)..(input.last_column)).map{ |col| 
    $rows << input.cell(row, col) if col != 5 and col <= 10}.join(" ") 
end 

J'ai cherché la réponse pendant des heures mais je ne trouve pas de solution.

Ce qui suit a fini par être ma solution viable:

((xlsx.first_row)..(xlsx.last_row)).each do |row| 
    ((xlsx.first_column)..(xlsx.last_column)).each do |col| 
    $tmp_row << xlsx.cell(row, col) if col != 5 and col <= 10 
    end 
remove_newlines_from_strings($tmp_row) 
$rows_sheet_0 << $tmp_row 
$tmp_row = [] 
end 

Répondre

1

Si vous utilisez 1.9+, vous pouvez profiter de Hashes commandés avec quelque chose comme ceci:

a_of_as = spreadsheet.group_by { |k, v| k.first }.map { |k, v| v.map(&:last) } 

Si vous n'êtes pas certain que le Hash sera construit dans le bon ordre, vous pouvez forcer la « coordonnées trier par ordre » comme ceci:

a_of_as = spreadsheet.sort_by { |k, v| k } 
        .group_by { |k, v| k.first } 
        .map  { |k, v| v.map(&:last) } 

Je suppose qu'il n'y a pas de trous dans la grille, mais cela semble être une hypothèse sûre quand on a affaire à un tableur.

Par exemple (reformaté pour la compacité):

>> pp spreadsheet 
{[1, 1]=>"string-1", [1, 2]=>"string-2", [1, 3]=>"string-3", [1, 4]=>"string-4", [1, 5]=>"string-5", [1, 6]=>"string-6", [1, 7]=>"string-7", 
[2, 1]=>"string-1", [2, 2]=>"string-2", [2, 3]=>"numeric-1", [2, 4]=>"numeric-2", [2, 5]=>"string-3", [2, 6]=>"string-4", [2, 7]=>"numeric-3", 
[3, 1]=>"string-1", [3, 2]=>"string-2", [3, 3]=>"numeric-1", [3, 4]=>"numeric-2", [3, 5]=>"string-3", [3, 6]=>"string-4", [3, 7]=>"numeric-3"} 

>> pp spreadsheet.group_by { |k, v| k.first }.map { |k, v| v.map(&:last) } 
[["string-1", "string-2", "string-3", "string-4", "string-5", "string-6", "string-7"], 
["string-1", "string-2", "numeric-1", "numeric-2", "string-3", "string-4", "numeric-3"], 
["string-1", "string-2", "numeric-1", "numeric-2", "string-3", "string-4", "numeric-3"]] 

>> spreadsheet2 = Hash[spreadsheet.sort { |(ka,va),(kb,vb)| kb <=> ka }] 
>> pp spreadsheet2 
{[3, 7]=>"numeric-3", [3, 6]=>"string-4", [3, 5]=>"string-3", [3, 4]=>"numeric-2", [3, 3]=>"numeric-1", [3, 2]=>"string-2", [3, 1]=>"string-1", 
[2, 7]=>"numeric-3", [2, 6]=>"string-4", [2, 5]=>"string-3", [2, 4]=>"numeric-2", [2, 3]=>"numeric-1", [2, 2]=>"string-2", [2, 1]=>"string-1", 
[1, 7]=>"string-7", [1, 6]=>"string-6", [1, 5]=>"string-5", [1, 4]=>"string-4", [1, 3]=>"string-3", [1, 2]=>"string-2", [1, 1]=>"string-1"} 

>> pp spreadsheet2.sort_by { |k,v| k }.group_by { |k, v| k.first }.map { |k, v| v.map(&:last) } 
[["string-1", "string-2", "string-3", "string-4", "string-5", "string-6", "string-7"], 
["string-1", "string-2", "numeric-1", "numeric-2", "string-3", "string-4", "numeric-3"], 
["string-1", "string-2", "numeric-1", "numeric-2", "string-3", "string-4", "numeric-3"]] 
+0

Merci pour la bonne suggestion. J'ai essayé et j'obtiens l'erreur suivante: méthode non définie 'group_by 'pour # user1411496

+0

@ user1411496:' spreadsheet' devrait être votre Hash, pas votre feuille de calcul réelle. –

+0

La feuille de calcul est mon hash ... input.default_sheet = input.sheets [0] (à partir de roo). Mon hachage est alors "entrée" ... – user1411496

1
h = {[1, 1]=>"string-1",[1, 2]=>"string-2",[1, 3]=>"string-3",[1, 4]=>"string-4", 
[1,5]=>"string-5",[1, 6]=>"string-6",[1, 7]=>"string-7",[2, 1]=>"string-1", 
[2, 2]=>"string-2",[2, 3]=>"numeric-1",[2, 4]=>"numeric-2",[2, 5]=>"string-3", 
[2, 6]=>"string-4",[2, 7]=>"numeric-3",[3, 1]=>"string-1",[3, 2]=>"string-2", 
[3, 3]=>"numeric-1",[3, 4]=>"numeric-2",[3, 5]=>"string-3",[3, 6]=>"string-4", 
[3, 7]=>"numeric-3"} 

h.each_with_object(Hash.new([])){ |m,res| res[m.first.first] += [m.last] }.values 

#=>[["string-1","string-2","string-3","string-4","string-5","string-6","string-7"], 
#=> ["string-1","string-2","numeric-1","numeric-2","string-3","string-4","numeric-3"], 
#=> ["string-1","string-2","numeric-1","numeric-2","string-3","string-4","numeric-3"]] 

Merci à mu est trop courte allusion, je peux réécrire un peu « s:

h.each_with_object(Hash.new{|h,k|h[k]=[]}) do |m,res| 
    res[m.first.first] << m.last 
end.values 
+1

Vous pourriez vouloir noter pourquoi vous ne tombez pas dans le piège 'Hash.new ([])' habituel. –

+0

Quel est le piège? – megas

+0

Regardez ce que '[1] .each_with_object (Hash.new ([])) {| i, h | h [i] << i} 'fait et vous devriez le voir. –

Questions connexes