这是您可以用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