我正在寻找一个脚本,方法或工具来对嵌套的降价列表进行排序。我使用sublime文本,它有一个内置的排序行函数,但是这个函数破坏了任何嵌套列表的顺序。例如,如果我想要排序:
* Zoo Animals
* Herbivores
* Zebra
* Gazelle
* Carnivores
* Tiger
* Lion
* Omnivores
* Gorilla
* Baboon
* Chimpanzee
* Domestic Animals
* Canines
* German Shepherd
* Cocker Spaniel
使用sublime排序行功能,我得到:
* Baboon
* Chimpanzee
* Cocker Spaniel
* Gazelle
* German Shepherd
* Gorilla
* Lion
* Tiger
* Zebra
* Canines
* Carnivores
* Herbivores
* Omnivores
* Domestic Animals
* Zoo Animals
显然,这不是我想要的。我想要的是一个"范围排序"哪个相对于每个项目符号级别进行排序,而不会破坏嵌套关系,如下所示:
* Domestic Animals
* Canines
* Cocker Spaniel
* German Shepherd
* Zoo Animals
* Carnivores
* Lion
* Tiger
* Herbivores
* Gazelle
* Zebra
* Omnivores
* Baboon
* Chimpanzee
* Gorilla
以下是我已经研究过的一些事情以及我对每个事物的看法:
您将如何排序大型嵌套降价列表?
更新#1:
@ J4G创建了一个很棒的Atom软件包来解决原始排序问题,请参阅他对该链接的回答。
上一个列表是一个没有代码块和编号列表的简单列表。但是,在对现实生活中的降价列表进行排序时,我们有代码块和编号列表以及以特殊字符开头的行 - 嵌套在列表中,如下所示:
* Commands
* Migrations
* `rake db:migrate` - push all migrations to the database
* 'STEP=3' - revert the last 3 migrations
* `Rails`
* `c` - start rails console, run code from your app!
* `Rake`
* Rake Task
```ruby
desc 'process csv'
task process_csv: :environment do
Node.process_csv
end
```
* Package Upgrade Status:
1. Install Package
2. Attach Plugin
3. Review Installation
~~~
|Install|Status|
|Yes|Pending|
~~~
排序后,我认为上面的降价列表应该保持不变,因为刻度线和引号没有排序重要性,并且已经按照正确的顺序创建了代码块/编号列表。
答案 0 :(得分:4)
如果您对使用Atom感兴趣(我强烈推荐它作为Sublime的免费替代品),我只是制作了一个包来做你需要的。
答案 1 :(得分:3)
这是使用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”或“here doc”。
puts sort_indented(str)
* Domestic Animals
* Canines
* Cocker Spaniel
* German Shepherd
* Zoo Animals
* Carnivores
* Lion
* Tiger
* Herbivores
* Gazelle
* Zebra
* Omnivores
* Baboon
* Chimpanzee
* Gorilla
一般方法
当Ruby对一组数组进行排序时,例如:
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
,所以Ruby继续讨论第三个元素,即领带被打破: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
的每个元素:
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
此计算的结果是我在上面的 General Approach 下给出的第一个数组。我们现在可以对result
进行排序,以获得我在一般方法下提供的第二个数组:
sorted = result.sort
最后两步是用最后一个非空字符串替换sorted
(三元素数组)的每个元素:
sorted_strings = sorted.map { |a| a[a.rindex { |s| s != '' }] }
然后将这些字符串连接成一个字符串:
sorted_strings.join("\n")
答案 2 :(得分:1)
如果有人仍然感兴趣,我为此创建了一个 vscode extension。
它不仅仅是一个作用域排序,它可以删除唯一值,它可以递归排序嵌套项,它可以不区分大小写等。
它还满足了 OP 在列表项下具有内容的其他要求。
代码可以在 github 上找到,这里是 actual implementation 的文件。
这里是文本形式,有点过时,因为较新的代码添加了更具体的选项:
call