我不确定这种类型的名称是否存在,所以我很难在其他地方找到相关的答案。
我希望元素尽可能地旋转。
鉴于此数组:
[38,38,40,40,40,41,41,41,41,60]
如何将其排序?
[38,40,41,60,38,40,41,40,41,41]
我研究过其他主题,但未能找到答案。
提前致谢!
答案 0 :(得分:3)
这本身并不是排序"排序"本身。这是一个排序步骤,但最终您真正尝试做的事情称为matrix transposition。
以下两种实现方式。
第一种方式更长,为了清晰起见,分解为更多步骤(希望如此)。
首先,我们将相关的数组元素排序并分组在一起:
v = arr.sort.group_by { |e| e }.values
# => [[38, 38], [40, 40, 40], [41, 41, 41, 41], [60]]
让我们为结果创建一个新数组:
r = []
现在我们将获得具有最多元素的那个:
max = arr.map { |e| arr.count(e) }.max
然后我们多次遍历数组,
max.times { ... }
每次从每个子阵列中拉出一个元素,然后将其放到结果数组中:
max.times { v.each { |a| r << a.shift } }; r.compact!
我们有答案:
# => [38, 40, 41, 60, 38, 40, 41, 40, 41, 41]
既然你已经看到了漫长的道路,那么这里的方法更为简洁。这并不需要尽可能多的迭代(或输出数组!)。
首先,我们将子数组填充为max
:
arr.sort.
group_by { |e| e }.values.
map { |a| a.fill(nil, a.size..max-1) }
# ...
现在这是max
个max
元素的正方形数组,因此我们可以将其视为方阵。这意味着我们可以转置元素,以便&#34;行&#34;成为&#34;列&#34;,反之亦然。
因此,我们transpose
,然后flatten
获取单个数组,然后compact
删除nil
元素:
# ...
(...).transpose.flatten.compact
我们得到了理想的结果:
# => [38, 40, 41, 60, 38, 40, 41, 40, 41, 41]
答案 1 :(得分:0)
这是另一种解决方法。看起来约翰已经给出了一个很好的答案,所以我不会详细解释这个问题。
要了解其工作原理,我建议添加一些puts
语句来查看中间值。您可以使用watch ruby sorter_test.rb
运行它以不断获得反馈。 (见watch docs)。
此处使用的大多数方法来自Enumerable
module。
require 'minitest/autorun'
class Sorter < Struct.new(:list)
def call
sorted_and_grouped = list.sort.group_by { |i| i }.values
max_len = sorted_and_grouped.max_by(&:count).count
padded = sorted_and_grouped.map { |xs| pad(xs, max_len) }
padded.reduce(&:zip).flatten.compact
end
private
def pad(xs, len)
xs.fill(nil, xs.count...len)
end
end
ORIGINAL = [38, 38, 40, 40, 40, 41, 41, 41, 41, 60].freeze
SORTED = [38, 40, 41, 60, 38, 40, 41, 40, 41, 41].freeze
class TestSorter < Minitest::Test
def test_sorts_as_expected
actual = Sorter.new(ORIGINAL).call
assert_equal SORTED, actual
end
end
答案 2 :(得分:0)
这是另一种方式。这取决于您的数组的排序(增加或减少),就像在您的示例中一样。而且,如果没有这种假设,问题就没有明确定义。
首先,我经常希望有一位帮手:
class Array
def %(arr)
arr.each_with_object(dup) do |e,a|
i = a.index(e)
a.delete_at(i) if i
end
end
end
例如:
arr = [38, 38, 40, 40, 40, 41, 41, 41, 41, 60]
arr % [41, 60, 40, 38, 40, 41]
#=> [38, 40, 41, 41]
如果a
和b
是两个数组,则a%b
与a-b
类似,只是删除a
中包含的所有b
元素。 {1}},它为a
中该角色的每个实例删除b
中的一个字符(索引最小的一个字符)。现在这不是一个方便的内置方法吗?
使用这个帮助器,以所需的方式对数组进行排序是一件简单的事情:
a
数组并创建一个空数组result
。u
的唯一元素a
添加到result
。u
删除a
。a
为空,请返回result
;否则重复第2步。此代码如下:
def steves_sort(arr)
a = arr.dup
result = []
while a.any?
u = a.uniq
result.concat(u)
a = a % u
end
result
end
steves_sort([38, 38, 40, 40, 40, 41, 41, 41, 41, 60])
#=> [38, 40, 41, 60, 38, 40, 41, 40, 41, 41]