[編輯:我最初的解決方案,這是繼此編輯,不會的修訂後的聲明中工作題。不過,我會放棄它,因爲它可能是有興趣的。
以下是根據修訂後的規則執行排序的一種方法,據我所知。如果我誤解了這些規則,我預計修正會很小。
正則表達式使用
讓我們先從正則表達式,我將使用:
R =/
\{ # match char
( # begin capture group
\d+ # match one or more digits
(?: # begin non-capture group
\. # match decimal
\d+ # match one or more digits
) # end non-capture group
| # or
\d* # match zero or more digits
) # match end capture group
\} # match char
/x
例子:
a = ["{5}something", "{61}{64}could", "{}be", "{54}{31.24}{0.2}write",
"{11}{21}{87}{65}here", "[]or", "{31}not", "{31} cat"]
a.each_with_object({}) { |s,h| h[s] = s.scan(R).flatten }
# => {"{5}something" =>["5"],
# "{61}{64}could" =>["61", "64"],
# "{}be" =>[""],
# "{54}{31.24}{0.2}write"=>["54", "31.24", "0.2"],
# "{11}{21}{87}{65}here" =>["11", "21", "87", "65"],
# "[]or" =>[],
# "{31}not" =>["31"]
# "{31} cat" =>["31"]}
custom_sort方法
我們可以寫方法custom_sort
如下(改sort_by
到sort_by!
爲custom_sort!
):
class Array
def custom_sort
sort_by do |s|
a = s.scan(R).flatten
raise SyntaxError,
"'#{s}' contains empty braces" if a.any?(&:empty?)
raise SyntaxError,
"'#{s}' contains zero or > 3 pair of braces" if a.size.zero?||a.size > 3
a.map(&:to_f) << s[a.join.size+2*a.size..-1].tr(' ', 255.chr)
end
end
end
例子
讓我們試一下:
a.custom_sort
#=> SyntaxError: '{}be' contains empty braces
刪除"{}be"
從a
:
a = ["{5}something", "{61}{64}could", "{54}{31.24}{0.2}write",
"{11}{21}{87}{65}here", "[]or", "{31}not", "{31} cat"]
a.custom_sort
#SyntaxError: '{11}{21}{87}{65}here' contains > 3 pair of braces
刪除"{11}{21}{87}{65}here"
:
a = ["{5}something", "{61}{64}could", "{54}{31.24}{0.2}write",
"[]or", "{31}not", "{31} cat"]
a.custom_sort
#=> SyntaxError: '[]or' contains zero or > 3 pair of braces
刪除"[]or"
:
a = ["{5}something", "{61}{64}could", "{54}{31.24}{0.2}write",
"{31}not", "{31} cat"]
a.custom_sort
#=> ["{5}something",
# "{31}not",
# "{31} cat",
# "{54}{31.24}{0.2}write", "{61}{64}could"]
說明
假設的一個字符串進行排序是:
s = "{54}{31.24}{0.2}write a letter"
然後在sort_by
塊,我們將計算:
a = s.scan(R).flatten
#=> ["54", "31.24", "0.2"]
raise SyntaxError, "..." if a.any?(&:empty?)
#=> raise SyntaxError, "..." if false
raise SyntaxError, "..." if a.size.zero?||a.size > 3
#=> SyntaxError, "..." if false || false
b = a.map(&:to_f)
#=> [54.0, 31.24, 0.2]
t = a.join
#=> "5431.240.2"
n = t.size + 2*a.size
#=> 16
u = s[n..-1]
#=> "wr i te"
v = u.tr(' ', 255.chr)
#=> "wr\xFFi\xFFte"
b << v
#=> [54.0, 31.24, 0.2, "wr\xFFi\xFFte"]
注意的是,使用String#tr(或者你可以使用String#gsub)把空間的ASCII字符排序順序的末尾:
255.times.all? { |i| i.chr < 255.chr }
#=> true
潮]
我假定,在排序,對字符串的是以如下方式analo進行比較一直到Array#<=>。第一次比較考慮了每個字符串中第一對大括號內的數字字符串(轉換爲浮點數後)。通過比較第二對大括號中的數字字符串(轉換爲浮點數)來打破關係。如果還有一條平行線,則比較大括號內的第三對數字等。如果一個字符串有兩對大括號,另一個有m > n
對,並且大括號內的值與第一對n
對相同,則我假設第一個字符串是在排序中的第二個字符串之前。
代碼
R =/
\{ # match char
(\d+) # capture digits
\} # match char
+ # capture one or more times
/x
class Array
def custom_sort!
sort_by! { |s| s.scan(R).map { |e| e.first.to_f } }
end
end
例
array = ["{109}{08} OK",
"{109}{07} OK",
"{98} Thx",
"{108}{0.8}{908} aa",
"{108}{0.8}{907} aa",
"{8}{51} lorem ipsum"]
a = array.custom_sort!
#=> ["{8}{51} lorem ipsum",
# "{98} Thx",
# "{108}{0.8}{907} aa",
# "{108}{0.8}{908} aa",
# "{109}{07} OK",
# "{109}{08} OK"]
array == a
#=> true
說明
現在讓我們來計算在Array#sort_by!的塊中的值的第一元件210
s = "{109}{08} OK"
a = s.scan(R)
#=> [["109"], ["08"]]
b = a.map { |e| e.first.to_f }
#=> [109.0, 8.0]
現在讓我們做其他弦相同,結果放一個數組:
c = array.map { |s| [s, s.scan(R).map { |e| e.first.to_f }] }
#=> [["{8}{51} lorem ipsum", [8.0, 51.0]],
# ["{98} Thx", [98.0]],
# ["{108}{0.8}{907} aa", [108.0, 907.0]],
# ["{108}{0.8}{908} aa", [108.0, 908.0]],
# ["{109}{07} OK", [109.0, 7.0]],
# ["{109}{08} OK", [109.0, 8.0]]]
在custom_sort!
sort_by
因此等效於:
c.sort_by(&:last).map(&:first)
#=> ["{8}{51} lorem ipsum",
# "{98} Thx",
# "{108}{0.8}{907} aa",
# "{108}{0.8}{908} aa",
# "{109}{07} OK",
# "{109}{08} OK"]
徹底,一如既往。好工作。 – DiegoSalazar
這是非常有用的解釋,非常感謝!但是對於字符串比較,我忘了提到一些東西。假設:[「{42} foo」,「{42}酒吧」,「{42}世界」,「{42}你好」]。訣竅在於比較字符串,空格字符''應該*在* alphanum之後,但在ASCII表格中,它不會。我在另一個線程(http://stackoverflow.com/questions/29808574/ruby-custom-string-sort)中看到我可以設置自己的「字符數組」命令。是否有可能將此功能集成到您的優雅解決方案中? – Rikouchi
今天晚些時候我會看看。同時,我建議你編輯你的問題,在你的評論中添加信息(並且如果需要,還可以糾正'108'和'109'的排序)。由於附加信息改變了問題,因此您需要在編輯中清楚地說明問題。通常這是通過編寫「編輯:我沒有提及...」來完成的,也許在問題的最後。 –