对于Ruby,是否有一个natural_sort_by方法?

时间:2022-05-11 16:00:32

I have a list of files with a bunch of attributes. One of the attributes is the file name which is how I would like to sort the list. However, the list goes something like this: filename 1, filename 2, filename 10, filename 20.

我有一个包含一系列属性的文件列表。其中一个属性是文件名,这是我想对列表进行排序的方式。但是,这个列表是这样的:文件名1,文件名2,文件名10,文件名20。

The ruby sort_by method produces this:

ruby sort_by方法产生如下:

files = files.sort_by { |file| file.name }
=> [filename 1, filename 10, filename 2, filename 20]

I would like a more human readable list like filename 1, filename 2, filename 10, filename 20

我想要一个更人类可读的列表,如文件名1,文件名2,文件名10,文件名20

I found the natural_sort gem but it seems to only work like the sort method. I need something where I can specify what to sort the array by.

我找到了natural_sort gem,但它似乎只像sort方法一样工作。我需要一些东西来指定数组的排序方式。

Any help?

任何帮助吗?

5 个解决方案

#1


7  

As long as files are always named "file #", you could do

只要文件总是命名为“file #”,您就可以这样做

files.sort_by{|f| f.name.split(" ")[1].to_i }

文件。f sort_by { | | f.name.split(" ")[1]。to_i }

This splits on the space, and grabs the number to do the sorting.

这将在空间上进行分割,并获取进行排序的编号。

#2


24  

Here's another take on a "natural" sort method:

下面是另一种“自然”排序方法:

class String
  def naturalized
    scan(/[^\d\.]+|[\d\.]+/).collect { |f| f.match(/\d+(\.\d+)?/) ? f.to_f : f }
  end
end

This converts something like "Filename 10" into a simple array with floats in place of numbers [ "Filename", 10.0 ]

这将“Filename 10”之类的内容转换为一个简单的数组,其中浮点数代替数字["Filename", 10.0]

You can use this on your list:

你可以在你的列表中使用这个:

files.sort_by! { |file| file.name.to_s.naturalized }

This has the advantage of working on arbitrary numbers in unpredictable positions. The paranoid .to_s call in that block is to ensure that there is a string and not an inadvertent nil when sorting.

这具有在不可预测的位置上处理任意数字的优点。该块中的偏执的.to_s调用是为了确保在排序时有一个字符串而不是无意的nil。

#3


13  

generic answer for strings natural sort

字符串自然排序的一般答案

array.sort_by {|e| e.split(/(\d+)/).map {|a| a =~ /\d+/ ? a.to_i : a }}

#4


6  

I've created a natural sort gem. It can sort by an attribute like this:

我创造了一颗天然的宝石。它可以通过如下属性进行排序:

# Sort an array of objects by the 'number' attribute
Thing = Struct.new(:number, :name)
objects = [
  Thing.new('1.1', 'color'),
  Thing.new('1.2', 'size'),
  Thing.new('1.1.1', 'opacity'),
  Thing.new('1.1.2', 'lightness'),
  Thing.new('1.10', 'hardness'),
  Thing.new('2.1', 'weight'),
  Thing.new('1.3', 'shape')
  ]
Naturally.sort_by(objects, :number)

# => [#<struct Thing number="1.1", name="color">,
      #<struct Thing number="1.1.1", name="opacity">,
      #<struct Thing number="1.1.2", name="lightness">,
      #<struct Thing number="1.2", name="size">,
      #<struct Thing number="1.3", name="shape">,
      #<struct Thing number="1.10", name="hardness">,
      #<struct Thing number="2.1", name="weight">]

#5


-3  

It is sorting correctly. The problem here is that the names aren't good to sort the way you want. In means of string, 10 comes before 2 and 21 comes before 5.

这是正确的排序。这里的问题是这些名称不适合按照您想要的方式进行排序。用字符串表示,10在2之前,21在5之前。

If you want it to sort it like it was numbers, you have 2 approaches:

如果你想把它排序成数字,你有两种方法:

1 - Change all your listings to add a leading 0 before numbers with just one digit.

1 -改变你所有的清单,在数字前加上一个0,只有一个数字。

2 - Do as William suggested, aplit the name, transform the string to integer and sort by it.

2 -按照William的建议,命名,将字符串转换为整型并对其进行排序。

I would recommend option 1 since the second rely on the padronization of the names.

我建议选择1,因为第二个选择依赖于名称的padronization。

#1


7  

As long as files are always named "file #", you could do

只要文件总是命名为“file #”,您就可以这样做

files.sort_by{|f| f.name.split(" ")[1].to_i }

文件。f sort_by { | | f.name.split(" ")[1]。to_i }

This splits on the space, and grabs the number to do the sorting.

这将在空间上进行分割,并获取进行排序的编号。

#2


24  

Here's another take on a "natural" sort method:

下面是另一种“自然”排序方法:

class String
  def naturalized
    scan(/[^\d\.]+|[\d\.]+/).collect { |f| f.match(/\d+(\.\d+)?/) ? f.to_f : f }
  end
end

This converts something like "Filename 10" into a simple array with floats in place of numbers [ "Filename", 10.0 ]

这将“Filename 10”之类的内容转换为一个简单的数组,其中浮点数代替数字["Filename", 10.0]

You can use this on your list:

你可以在你的列表中使用这个:

files.sort_by! { |file| file.name.to_s.naturalized }

This has the advantage of working on arbitrary numbers in unpredictable positions. The paranoid .to_s call in that block is to ensure that there is a string and not an inadvertent nil when sorting.

这具有在不可预测的位置上处理任意数字的优点。该块中的偏执的.to_s调用是为了确保在排序时有一个字符串而不是无意的nil。

#3


13  

generic answer for strings natural sort

字符串自然排序的一般答案

array.sort_by {|e| e.split(/(\d+)/).map {|a| a =~ /\d+/ ? a.to_i : a }}

#4


6  

I've created a natural sort gem. It can sort by an attribute like this:

我创造了一颗天然的宝石。它可以通过如下属性进行排序:

# Sort an array of objects by the 'number' attribute
Thing = Struct.new(:number, :name)
objects = [
  Thing.new('1.1', 'color'),
  Thing.new('1.2', 'size'),
  Thing.new('1.1.1', 'opacity'),
  Thing.new('1.1.2', 'lightness'),
  Thing.new('1.10', 'hardness'),
  Thing.new('2.1', 'weight'),
  Thing.new('1.3', 'shape')
  ]
Naturally.sort_by(objects, :number)

# => [#<struct Thing number="1.1", name="color">,
      #<struct Thing number="1.1.1", name="opacity">,
      #<struct Thing number="1.1.2", name="lightness">,
      #<struct Thing number="1.2", name="size">,
      #<struct Thing number="1.3", name="shape">,
      #<struct Thing number="1.10", name="hardness">,
      #<struct Thing number="2.1", name="weight">]

#5


-3  

It is sorting correctly. The problem here is that the names aren't good to sort the way you want. In means of string, 10 comes before 2 and 21 comes before 5.

这是正确的排序。这里的问题是这些名称不适合按照您想要的方式进行排序。用字符串表示,10在2之前,21在5之前。

If you want it to sort it like it was numbers, you have 2 approaches:

如果你想把它排序成数字,你有两种方法:

1 - Change all your listings to add a leading 0 before numbers with just one digit.

1 -改变你所有的清单,在数字前加上一个0,只有一个数字。

2 - Do as William suggested, aplit the name, transform the string to integer and sort by it.

2 -按照William的建议,命名,将字符串转换为整型并对其进行排序。

I would recommend option 1 since the second rely on the padronization of the names.

我建议选择1,因为第二个选择依赖于名称的padronization。