Legyen az adat egy tömbben:
t = ["hello 15", "hello 2", "world"]
Kód:
# add preceeding zeros to every numeric part in a text
def pad2(text)
zeros = 20
res = ""
a1 = text.split(/[0-9]+/)
a2 = text.scan(/[0-9]+/)
if a2.size > 0
c = [a1.size, a2.size].max
i = 0
loop{
x1 = a1[i]
x2 = a2[i]
if x1
res << x1
end
if x2
len = zeros - x2.size
len = 0 if len < 0
x3 = "0" * len + x2
res << x3
end
i += 1
break if i >= c
}
else
res = text
end
return res
end
t2 = t.sort_by{|x| pad2(x)}
p t2
Eredmény:
["hello 2", "hello 15", "world"]
Lásd még a kapcsolódó előző blogbejegyzésem.
toMpEr ötletét felhasználva egy jobb metódus:
p t.sort_by{|x| x.split(/(\d+)/).map{|x| x[/\d/] ? x.to_i : x} }
Egy strip-et beletettem még, hogy ne számítson a sorbarendezésnél a szóközök (és tab-ok) mennyisége, vagyis "hello 1" és "hello 1" bemenetet vegye egyformának:
p t.sort_by{|x| x.split(/(\d+)/).map{|x| x[/\d/] ? x.to_i : x.strip} }
- log69 blogja
- A hozzászóláshoz be kell jelentkezni
- 1517 megtekintés
Hozzászólások
Python:
t = ["hello 15", "hello 2", "hello", "hello a", "world"]
def strSorter(key):
if " " in key:
pre, last_word = key.rsplit(" ", 1)
if last_word.isdigit():
return (pre, int(last_word))
else:
return (key, 0)
else:
return (key, 0)
t2 = sorted(t, key=strSorter)
assert t2 == ['hello', 'hello 2', 'hello 15', 'hello a', 'world']
Bar Ruby-t nem ismerem, de ott is biztos van lehetoseg tobb szintu sort-ra.
- A hozzászóláshoz be kell jelentkezni
Nem egészen jó az általad írt kód. Nem univerzális. Ha jól olvasom akkor szóközzel osztod fel és az utolsó szót (részt) nézed hogy szám-e stb. Viszont ez nem működik bármilyen kombinációra, pl:
ez egy példa 1111 van további része is 4433 és egyéb szöveg
ez egy példa 2 itt meg még több szöveg van
Az én algo-m jól rendezi, de a tiéd pedig nem.
- A hozzászóláshoz be kell jelentkezni
Amennyiben ez kovetelmeny:
import re
t = [
"hello 15", "hello 2", "hello", "hello a", "world",
"ez egy pelda 2 valami van meg hatra 15", "ez egy pelda 15 valami van meg hatra", "ez egy pelda 2 valami van meg hatra 2"
]
def strSorter(key):
parts = re.split("([0-9]+)", key)
parts = [int(part) if part.isdigit() else part for part in parts]
return parts
t2 = sorted(t, key=strSorter)
assert t2 == [
'ez egy pelda 2 valami van meg hatra 2', 'ez egy pelda 2 valami van meg hatra 15', 'ez egy pelda 15 valami van meg hatra',
'hello', 'hello 2', 'hello 15', 'hello a', 'world'
]
- A hozzászóláshoz be kell jelentkezni
Ez még jobb ötlet mint az enyém, hogy tömbként hasonlítod össze a rendezéshez úgy, hogy a szám részeket számmá konvertálod. Tetszik. A Ruby kódom ehhez:
p t.sort_by{|x| x.split(/(\d+)/).map{|x| x[/\d/] ? x.to_i : x} }
- A hozzászóláshoz be kell jelentkezni
Huhh... Ez nagyon trükkös. Mert ugye ezeket így nem lehetne összehasonlítani: [2] > ["string"], de az strSorter() ebből: ["2"], ezt készíti el: ["",2,""] .
--
eutlantis
- A hozzászóláshoz be kell jelentkezni
"Nem egészen jó az általad írt kód. Nem univerzális."
Khm.
>> ["hello 98765432109876543210", "hello 123456789012345678901234567890"].sort_by{|x| pad2(x)}
=> ["hello 123456789012345678901234567890", "hello 98765432109876543210"]
- A hozzászóláshoz be kell jelentkezni
zeros = 20, ide ha 100-at írsz jó lesz.
- A hozzászóláshoz be kell jelentkezni
Attól, hogy erre az inputra is az elvárt kimenetet adja, még nem lesz se univerzális, se jó.
- A hozzászóláshoz be kell jelentkezni
Dehogynem jó a kimenet. A "zeros" változóval egy memóriabeli limitet szabtam, sok esetben fontos lehet. Írhatsz oda 1000-et is csak nem biztos hogy érdemes. Illetve univerzális alatt azt értem hogy bármilyen inputra működjön.
- A hozzászóláshoz be kell jelentkezni
szerk: ja semmi.
- A hozzászóláshoz be kell jelentkezni
Mint a mellékelt ábra is mutatja, nem működik bármilyen inputra.
- A hozzászóláshoz be kell jelentkezni
Leteszteltem, nekem igen. Átírtad a "zeros = 20" sort? írjál oda 200-at mondjuk.
- A hozzászóláshoz be kell jelentkezni
Miért próbáltam volna? Nyilvánvaló, hogy bármekkora számot is írsz oda, attól hosszabb, nem ugyanolyan hosszú számsorozatokra nem fog jól működni.
- A hozzászóláshoz be kell jelentkezni
Nincs bármekkora szám véges memória mellett.
Kiegészítés: ez megadja a limitet ha nem tetszik neked a fix szám:
zeros = t.map{|x|x.size}.max
- A hozzászóláshoz be kell jelentkezni
"t.map{|x|x.size}.max"
N darab string közül a leghosszabb hosszának megtalálásához feltétlenül szükség van egy másik N elemű tömbre?
Ha már véges memória, ugye :)
- A hozzászóláshoz be kell jelentkezni
Nem, úgy gondoltam hogy az eredetin futtatjuk.
- A hozzászóláshoz be kell jelentkezni
Hm? Tisztában vagy azzal, hogy az a sor mit csinál?
>> ["a", "b", "c"].map{|x|x.size}
=> [1, 1, 1]
- A hozzászóláshoz be kell jelentkezni
A végéről lehagytad a .max parancsot. Lásd ezt:
["hello world", "banana", "this is some sample text"].map{|x|x.size}.max
=> 24
Tehát mondhatom hogy 24 darab nullánál biztos hogy nem fog kelleni több a rendezéshez., merthogy ennyi karakter hosszú a leghosszabb szöveg. Tehát ha csak számból áll, pl 1, akkor sem kell hosszabb, tehát meghúzhatjuk a limitet itt.
- A hozzászóláshoz be kell jelentkezni
Vagyis fogalmad sincs, hogy valójában mit csinál.
Azért hagytam le a .max-ot, hogy a visszaadott értékből egyértelműen látszódjon, hogy közben létrejön egy másik tömb is.
- A hozzászóláshoz be kell jelentkezni
A létrejövő tömbben csak egész számok vannak, a mérete elenyésző az eredetihez képest, de a fenti egysoros megoldáshoz képest ez a vonal már nem releváns.
- A hozzászóláshoz be kell jelentkezni
$ printf "world\nhello 15\nhello 2\n" | sort --version-sort
hello 2
hello 15
world
Nem értem, miért kell túlbonyolítani :)
- A hozzászóláshoz be kell jelentkezni
Nem minden sort utilnak van --version-sort opciója.
- A hozzászóláshoz be kell jelentkezni
Ha jól gondolom, valójában a természetes rendezést keres(t)ed.
Python:
>>> import natsort
>>> t = ["hello 15", "hello 2", "world"]
>>> natsort.natsorted(t)
['hello 2', 'hello 15', 'world']
Bizonyára van ilyen modul Rubyban is.
- A hozzászóláshoz be kell jelentkezni
Rákeresek ezen a néven, kösz.
Szerk.: beépítve nem találok egyelőre. Külső megoldásból sok van, de akkor inkább maradok a fenti egysorosnál.
- A hozzászóláshoz be kell jelentkezni
Szerintem a "ruby version sort" sok használható találatot ad :)
- A hozzászóláshoz be kell jelentkezni
"natural sort" néven kerestem, de "ruby version sort" sem ad találatot beépített megoldásra. Érthető módon mindenki a sort_by metódussal operál.
- A hozzászóláshoz be kell jelentkezni
Úgy értettem, hogy valami plusz gem-et lehet telepíteni, ami ezt megcsinálja neked. Bár nyilván nem ez a legbonyolultabb feladat :)
- A hozzászóláshoz be kell jelentkezni
Ok, viszont a fenti 1 sor helyett a gem már tényleg rosszabb, mert függ a kód annak a karbantartójától, függőségek verziójától stb.
- A hozzászóláshoz be kell jelentkezni
+1
https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/
Szerk: ami nekem meg mindig nem tiszta ezzel a sztorival kapcsolatban: az npm-nek nincs valami local repoja mint a mavennek? Minden clean buildnel a kozponti repobol huzza a fuggosegeket?
Szerk2: ahogy latom nincs neki by default: https://www.npmjs.com/package/local-npm
Komolyan, a JS wannabe-k meg egy jol mukodo okoszisztemat se tudnak rendesen lemasolni? Mondjuk igy legalabb konzisztensek a JavaScripttel, az is nelkuloz minden jozan eszt.
- A hozzászóláshoz be kell jelentkezni
Vagy ha nem akarsz natsort vagy egyéb kész modult használni:
#!/usr/bin/python
t = ['hello 15', 'hello 2', 'world']
ts = map(lambda x: (x+' 999999999').split(), t) # hogy tuti legyen x[1]-ed
ts.sort(key=lambda x: int(x[1]))
ts = map(lambda x: x[:-1], ts)
print ts
- A hozzászóláshoz be kell jelentkezni