Jak mogę wyprowadzać zera wiodące w Rubim?

238

Wyprowadzam zestaw plików numerowanych ze skryptu Ruby. Liczby pochodzą z inkrementacji licznika, ale aby ładnie je sortować w katalogu, chciałbym używać początkowych zer w nazwach plików. Innymi słowy

plik_001 ...

zamiast

plik_1

Czy istnieje prosty sposób dodawania zer wiodących podczas konwersji liczby na ciąg? (Wiem, że mogę zrobić „jeśli mniej niż 10 .... jeśli mniej niż 100”).

Nathan Long
źródło

Odpowiedzi:

281

Jeśli znana jest maksymalna liczba cyfr w liczniku (np. N = 3 dla liczników 1..876), możesz to zrobić

str = "file_" + i.to_s.rjust(n, "0")
alex.zherdev
źródło
8
Heh heh, nie najlepsza odpowiedź, ale nie wiedziałem o rjust i używam rubinu od lat. Twoje zdrowie!
pauliephonic
Muszę zagłosować, bo wydaje się, że% 03s wstawia spacje z jakiegoś dziwnego powodu (% 03d wydaje się działać dobrze). W obu przypadkach mogłem przysiąc, że C był wypełniony zerami.
Nerdmaster
W końcu zmieniłem to na akceptowaną odpowiedź, ponieważ jest najprostsza i najłatwiejsza do zapamiętania. %działa, ale ma bardziej ogólny cel.
Nathan Long
nieoczekiwany, ale najłatwiejszy
akostadinov
1
Przybyłem tutaj, aby wpisać numer 36. To działa, podczas gdy% wygląda na to, że nie. Dzięki!
Ethan Kamiński
344

Użyj %operatora z ciągiem znaków:

irb(main):001:0> "%03d" % 5
=> "005"

Lewa strona to ciąg formatu printf, a prawa strona może być listą wartości, więc możesz zrobić coś takiego:

irb(main):002:0> filename = "%s/%s.%04d.txt" % ["dirname", "filename", 23]
=> "dirname/filename.0023.txt"

Oto ściągawka w formacie printf , która może być przydatna w tworzeniu ciągu formatu. Format printf pochodzi pierwotnie z Cfunkcji printf, ale podobne funkcje formatowania są dostępne w Perlu, Ruby, Pythonie, Javie, PHP itp.

Daniel Martin
źródło
1
Wspaniały! Zatem „% s” oznacza „zastąp tutaj N-tą wartość”, a „% 03d” oznacza „zastąp tutaj liczbę, dodając tyle zer, ile potrzeba, aby była to 3-cyfrowa liczba?” (Zgaduję, że d oznacza „cyfry”). Widzę teraz dokumentację na ten temat ( ruby-doc.org/core/classes/String.html#M000770 ), ale jest bardzo zwięzły i chciałbym trochę rozwinąć .
Nathan Long,
1
Dodałem link do ściągawki w formacie printf. „s” oznacza „ciąg”, „d” oznacza „liczbę dziesiętną”. „03” oznacza „pad do 3 znaków z zerami”; „% 3d” padnie po lewej stronie spacjami.
Daniel Martin,
2
BTW - to jest to samo, co dzwonienie Kernel#sprintf, co jest udokumentowane tutaj: ruby-doc.org/core-1.9.3/Kernel.html#method-i-sprintf
Nathan Long
Dodając do komentarza @ NathanLong, pierwszy przykład w tej odpowiedzi zostałby zapisany jako sprintf("%03d", 5).
Dennis
To powinna być wybrana odpowiedź.
Dan Barron
50

Czy nie możesz po prostu sformatować ciągu wartości przed skonkatowaniem nazwy pliku?

"%03d" % number
Lalafur Waage
źródło
Myślę, że ta odpowiedź nic nie dodaje do odpowiedzi @Daniela Martina, jednak podoba mi się jej prostota ...
svelandiag
3
Odpowiedział w tej samej minucie co Daniel Martin, więc prawdopodobnie nie wiedział o powielaniu.
Kurt Peek
Jest to idealne rozwiązanie dla utc_offset
Abel
30

Użyj String#nextjako licznika.

>> n = "000"
>> 3.times { puts "file_#{n.next!}" }
file_001
file_002
file_003

next jest stosunkowo „sprytny”, co oznacza, że ​​możesz nawet wybrać

>> n = "file_000"
>> 3.times { puts n.next! }
file_001
file_002
file_003
testr
źródło
Dzięki za zwrócenie na to uwagi. To taka niesamowita metoda.
Weston Ganger
9

Jak stwierdzono w innych odpowiedziach, "%03d" % numberdziała całkiem dobrze, ale jest sprzeczne z przewodnikiem po stylu ruby :

Preferuj użycie sprintf i jego formatu aliasu zamiast dość tajemniczej metody String #%

Możemy uzyskać ten sam wynik w bardziej czytelny sposób, używając:

format('%03d', number)
Rodrigo Vasconcelos
źródło
1
Jeśli Twoim celem jest nauczenie się niejasnej funkcji języka Ruby, użyj aliasu format. Jeśli Twoim celem jest ułatwienie zrozumienia kodu, powinieneś go użyć sprintf, ponieważ jest on częścią standardowej biblioteki C. Ta nazwa jest używana w różnych językach programowania. O wiele więcej ludzi rozumie, co sprintfrobi, w porównaniu do liczby, która wie, że formatto alias. To, że coś jest częścią RuboCop, nie powoduje, że jest z natury dobre lub złe. Wybierz reguły, które najlepiej pasują do twojego projektu. '%03d' % numberjest jeszcze łatwiejszy do odczytania.
Tilo,
1
Przeszedłem przez tę samą pętlę, zmieniając "%02d" % numna sprintf(...), a następnie format(...)według sugestii RuboCop. Uznałem wtedy, że jest sprintfto bardziej konwencjonalne niż format, dlatego zaktualizowałem rubocop.yml Style/FormatString: EnforcedStyle: sprintfi teraz dobrze śpię w nocy.
David Hempy
1

filenames = '000'.upto('100').map { |index| "file_#{index}" }

Wyjścia

[file_000, file_001, file_002, file_003, ..., file_098, file_099, file_100]

Ivan
źródło