這是您可以用Ruby做到的一種方法。假設字符串由變量str
保存。
代碼
def sort_indented(str)
arr = str.lines.map { |s| [indentation(s), s.chomp] }
indent_offset = arr.map(&:first).uniq.sort.each_with_index.
with_object({}) { |(indent, i),h| h[indent] = i }
dim_size = indent_offset.size
prev = []
arr.map do |indent, s|
a = ['']*dim_size
offset = indent_offset[indent]
a[offset] = s
a[0,offset] = prev.first(offset)
prev = a
a
end.sort.map { |a| a[a.rindex { |s| s != '' }] }.join("\n")
end
def indentation(s)
s[/^\s*/].size
end
例
str =<<THE_END
* Zoo Animals
* Herbivores
* Zebra
* Gazelle
* Carnivores
* Tiger
* Lion
* Omnivores
* Gorilla
* Baboon
* Chimpanzee
* Domestic Animals
* Canines
* German Shepherd
* Cocker Spaniel
THE_END
在Ruby此構造用於定義字符串文字被稱爲 「here document」,或 「在這裏的文檔」。
puts sort_indented(str)
* Domestic Animals
* Canines
* Cocker Spaniel
* German Shepherd
* Zoo Animals
* Carnivores
* Lion
* Tiger
* Herbivores
* Gazelle
* Zebra
* Omnivores
* Baboon
* Chimpanzee
* Gorilla
一般方法
當紅寶石排序數組的數組,如:
a = [1,2,4]
b = [4,5,6]
c = [1,2,3,5]]
[a, b, c]
它將在前排序每個陣列的第一個元素。由於a
和c
在偏移量零處具有相同的元素1
,並且b
在該偏移處具有4
,所以a
和c
都將在排序後的數組中出現在b
之前。 Ruby看着a
和c
的第二個元素打破平局。因爲他們都等於2
,紅寶石進入第三個元素,其中的平局被打破:c
在a
之前,因爲3 < 4
。
我會arr
轉換成下面的數組:
result =
[["* Zoo Animals" , "" , ""],
["* Zoo Animals" , " * Herbivores", ""],
["* Zoo Animals" , " * Herbivores", " * Zebra"],
["* Zoo Animals" , " * Herbivores", " * Gazelle"],
["* Zoo Animals" , " * Carnivores", ""],
["* Zoo Animals" , " * Carnivores", " * Tiger"],
["* Zoo Animals" , " * Carnivores", " * Lion"],
["* Zoo Animals" , " * Omnivores" , ""],
["* Zoo Animals" , " * Omnivores" , " * Gorilla"],
["* Zoo Animals" , " * Omnivores" , " * Baboon"],
["* Zoo Animals" , " * Omnivores" , " * Chimpanzee"],
["* Domestic Animals", "" , ""],
["* Domestic Animals", " * Canines" , ""],
["* Domestic Animals", " * Canines" , " * German Shepherd"],
["* Domestic Animals", " * Canines" , " * Cocker Spaniel"]]
一旦以這種形式,我們可以排序:
result.sort
#=> [["* Domestic Animals", "", ""],
# ["* Domestic Animals", " * Canines", ""],
# ["* Domestic Animals", " * Canines", " * Cocker Spaniel"],
# ["* Domestic Animals", " * Canines", " * German Shepherd"],
# ["* Zoo Animals", "", ""], ["* Zoo Animals", " * Carnivores", ""],
# ["* Zoo Animals", " * Carnivores", " * Lion"],
# ["* Zoo Animals", " * Carnivores", " * Tiger"],
# ["* Zoo Animals", " * Herbivores", ""],
# ["* Zoo Animals", " * Herbivores", " * Gazelle"],
# ["* Zoo Animals", " * Herbivores", " * Zebra"],
# ["* Zoo Animals", " * Omnivores", ""],
# ["* Zoo Animals", " * Omnivores", " * Baboon"],
# ["* Zoo Animals", " * Omnivores", " * Chimpanzee"],
# ["* Zoo Animals", " * Omnivores", " * Gorilla"]]
的最後一步是提取從每個最後一個非空字符串排序數組的元素。
詳解
首先我們定義一個輔助方法來計算一個字符串的縮進:
def indentation(s)
s[/^\s*/].size
end
例如,
#1234
indentation(" * Herbivores")
#=> 4
現在讓字符串轉換爲線陣列:
a = str.lines
#=> ["* Zoo Animals\n",
# " * Herbivores\n",
# " * Zebra\n",
# " * Gazelle\n",
# " * Carnivores\n",
# " * Tiger\n",
# " * Lion\n",
# " * Omnivores\n",
# " * Gorilla\n",
# " * Baboon\n",
# " * Chimpanzee\n",
# "* Domestic Animals\n",
# " * Canines\n",
# " * German Shepherd\n",
# " * Cocker Spaniel\n"]
接下來,我們轉換a
到對一個陣列,所述一對被的a
(字符串)的元件的第二元件,與所述換行砍掉結束時,第一個是它的縮進:
arr = a.map { |s| [indentation(s), s.chomp] }
# => [[0, "* Zoo Animals"], [4, " * Herbivores"],
# [8, " * Zebra"], [8, " * Gazelle"],
# [4, " * Carnivores"], [8, " * Tiger"],
# [8, " * Lion"], [4, " * Omnivores"],
# [8, " * Gorilla"], [8, " * Baboon"],
# [8, " * Chimpanzee"], [0, "* Domestic Animals"],
# [4, " * Canines"], [8, " * German Shepherd"],
# [8, " * Cocker Spaniel"]]
事實上,我們會一步執行前兩個操作:
arr = str.lines.map { |s| [indentation(s), s.chomp] }
接下來,我們需要知道所使用的縮進:
indents = arr.map { |pair| pair.first }
#=> [0, 4, 8, 8, 4, 8, 8, 4, 8, 8, 8, 0, 4, 8, 8]
,我們可以寫更多的經濟是這樣的:
indents = arr.map(&:first)
要查找唯一縮進我們寫:
unique = indents.uniq
#=> [0, 4, 8]
如果他們不是爲了,我們應該對它們進行排序:
sorted = unique.sort
#=> [0, 4, 8]
這三個縮進中的每一個都將對應我們要排序的數組中的偏移量,所以構造一個散列很方便:
indent_offset = sorted.each_with_index.with_object({}) do |(indent, i),h|
h[indent] = i
end
#=> {0=>0, 4=>1, 8=>2}
同樣,我們可以通過組合幾個步驟執行此計算:
indent_offset = arr.map(&:first).uniq.sort.each_with_index.
with_object({}) { |(indent, i),h| h[indent] = i }
接下來我們取代的arr
每個元素與串的3個元素數組:
dim_size = indent_offset.size
#=> 3
prev = []
result = arr.map do |indent, s|
a = ['']*dim_size
offset = indent_offset[indent]
a[offset] = s
a[0,offset] = prev.first(offset)
prev = a
a
end
結果這個計算是我在上面給出的第一個數組。現在,我們可以排序result
獲得我下一般方法給了第二陣:
sorted = result.sort
最後兩個步驟來替換最後一個非空字符串sorted
每個元素(一個三元素的數組) :
sorted_strings = sorted.map { |a| a[a.rindex { |s| s != '' }] }
再加入這些字符串成一個字符串:
sorted_strings.join("\n")
看起來沒有被任何人解決。如果你願意,我可以非常快速地在Node中寫一個。 – Harangue