Łatwo jest wczytać plik CSV do tablicy za pomocą Ruby, ale nie mogę znaleźć dobrej dokumentacji na temat zapisywania tablicy w pliku CSV. Czy ktoś może mi powiedzieć, jak to zrobić?
Odpowiedź, którą masz, jest świetna, ale zachęcam do nieużywania CSV. Jeśli nie masz tabulatorów w danych, łatwiej jest sobie radzić z plikami rozdzielanymi tabulatorami, ponieważ nie wymagają one aż tak cholernego cytowania i ucieczki. Jeśli musisz użyć CSV, oczywiście są to przerwy.
Bill Dueber
8
@Bill, moduł CSV starannie obsługuje pliki rozdzielane tabulatorami, a także rzeczywiste pliki csv. Opcja: col_sep pozwala określić separator kolumn jako „\ t” i wszystko jest w porządku.
@David to tryb plików. „w” oznacza zapis do pliku. Jeśli nie określisz tego, domyślnie będzie to „rb” (tryb binarny tylko do odczytu) i wystąpi błąd podczas próby dodania do pliku csv. Zobacz ruby-doc.org/core-1.9.3/IO.html, aby uzyskać listę prawidłowych trybów plików w Rubim.
Dylan Markow
15
Gotcha A dla przyszłych użytkowników, jeśli chcesz, aby każda iteracja nie zastępowała poprzedniego pliku csv, skorzystaj z opcji „ab”.
Hmm @tamouse, ta treść jest dla mnie nieco myląca bez czytania źródła csv, ale ogólnie, zakładając, że każdy skrót w twojej tablicy ma tę samą liczbę par k / v i że klucze są zawsze takie same, w tej samej kolejności (tj. jeśli twoje dane są uporządkowane), powinno to zrobić:
rowid =0
CSV.open(fn,'w')do|csv|
hsh_ary.each do|hsh|
rowid +=1if rowid ==1
csv << hsh.keys# adding header row (column labels)else
csv << hsh.values
end# of if/else inside hshend# of hsh's (rows)end# of csv open
Jeśli twoje dane nie są uporządkowane, to oczywiście nie zadziała
Wciągnąłem plik CSV za pomocą CSV.table, wykonałem pewne manipulacje, pozbyłem się niektórych kolumn, a teraz chcę ponownie buforować wynikową tablicę skrótów jako CSV (naprawdę rozdzieloną tabulatorami). Jak? gist.github.com/4647196
tamouse
hmm ... ta treść jest nieco nieprzejrzysta, ale biorąc pod uwagę tablicę skrótów, wszystkie z tą samą liczbą par k / v i tymi samymi kluczami, w tej samej kolejności ...
boulder_ruby
Dzięki, @boulder_ruby. To zadziała. Dane są tabelą spisu ludności, a ta istota jest raczej nieprzejrzysta, patrząc na nią. :) Zasadniczo wyodrębnia niektóre kolumny z oryginalnej tabeli spisu ludności do podzbioru.
tamouse
3
Nadużywasz injecttutaj, naprawdę chcesz z niego korzystać map. Ponadto nie musisz przekazywać pustego ciągu join, ponieważ jest to ustawienie domyślne. Możesz więc zmniejszyć to jeszcze bardziej:rows.map(&CSV.method(:generate_line).join
iGEL
1
Drugi przykład jest zbyt skomplikowany, ponieważ biblioteka CSV jest dość potężna. CSV.generate(headers: hsh.first&.keys) { |csv| hsh.each { |e| csv << e } }generuje równoważny CSV.
Jeśli ktoś jest zainteresowany, oto kilka linijek (i uwaga na temat utraty informacji o typie w CSV):
require 'csv'
rows =[[1,2,3],[4,5]]# [[1, 2, 3], [4, 5]]# To CSV string
csv = rows.map(&:to_csv).join # "1,2,3\n4,5\n"# ... and back, as String[][]
rows2 = csv.split("\n").map(&:parse_csv)# [["1", "2", "3"], ["4", "5"]]# File I/O:
filename ='/tmp/vsc.csv'# Save to file -- answer to your question
IO.write(filename, rows.map(&:to_csv).join)# Read from file# rows3 = IO.read(filename).split("\n").map(&:parse_csv)
rows3 = CSV.read(filename)
rows3 == rows2 # true
rows3 == rows # false
Uwaga: CSV traci wszystkie informacje o typie, możesz użyć JSON, aby zachować podstawowe informacje o typie, lub przejść do pełnego (ale łatwiejszego do edycji przez człowieka) YAML, aby zachować wszystkie informacje o typie - na przykład, jeśli potrzebujesz typu daty, który stałby się ciągi w CSV i JSON.
Btw, uważaj na wielowymiarowe tablice na wyciągnięcie ręki na JRuby. [ %w(your array), %w(goes here) ]nie będzie ładnie wyglądać. github.com/pry/pry/issues/568
Odpowiedzi:
Do pliku:
Do ciągu:
Oto aktualna dokumentacja dotycząca CSV: http://ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html
źródło
Mam tylko jedną linię.
Wykonaj wszystkie powyższe czynności i zapisz w pliku csv w jednym wierszu.
UWAGA:
Myślę, że konwersja bazy danych aktywnych rekordów do csv byłaby czymś takim
Hmm @tamouse, ta treść jest dla mnie nieco myląca bez czytania źródła csv, ale ogólnie, zakładając, że każdy skrót w twojej tablicy ma tę samą liczbę par k / v i że klucze są zawsze takie same, w tej samej kolejności (tj. jeśli twoje dane są uporządkowane), powinno to zrobić:
Jeśli twoje dane nie są uporządkowane, to oczywiście nie zadziała
źródło
inject
tutaj, naprawdę chcesz z niego korzystaćmap
. Ponadto nie musisz przekazywać pustego ciągujoin
, ponieważ jest to ustawienie domyślne. Możesz więc zmniejszyć to jeszcze bardziej:rows.map(&CSV.method(:generate_line).join
CSV.generate(headers: hsh.first&.keys) { |csv| hsh.each { |e| csv << e } }
generuje równoważny CSV.Jeśli masz tablicę tablic danych:
Następnie możesz zapisać to do pliku w następujący sposób, który moim zdaniem jest znacznie prostszy:
źródło
Jeśli ktoś jest zainteresowany, oto kilka linijek (i uwaga na temat utraty informacji o typie w CSV):
Uwaga: CSV traci wszystkie informacje o typie, możesz użyć JSON, aby zachować podstawowe informacje o typie, lub przejść do pełnego (ale łatwiejszego do edycji przez człowieka) YAML, aby zachować wszystkie informacje o typie - na przykład, jeśli potrzebujesz typu daty, który stałby się ciągi w CSV i JSON.
źródło
Opierając się na odpowiedzi @ boulder_ruby, właśnie tego szukam, zakładając, że
us_eco
zawiera tabelę CSV z mojej treści.Zaktualizowano treść na https://gist.github.com/tamouse/4647196
źródło
Sam sobie z tym walczę. Oto moje zdanie:
https://gist.github.com/2639448 :
źródło
[ %w(your array), %w(goes here) ]
nie będzie ładnie wyglądać. github.com/pry/pry/issues/568