Arrays 顺序排序
具有包含两个distincts元素的无序数组:Arrays 顺序排序,arrays,ruby,sorting,Arrays,Ruby,Sorting,具有包含两个distincts元素的无序数组: arr = ["portrait", "landscape", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "l
arr = ["portrait", "landscape", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "portrait", "landscape", "landscape"]
在此示例中,查看“排序”阵列,使其每四幅肖像中有一幅风景画:
如果不是一条直线,那么实现这一目标的最短途径是什么?在不知道回退是什么意思的情况下,下面是如何实现您想要的目标的示例。这可能不是最优雅的解决方案,但很简单:
#!/usr/bin/env ruby
arr = (['P'] * 32 + ['L'] * 12).shuffle # as an example
ps, ls = arr.partition { |element| element == 'P' }
result = []
loop do
portrait_count = [4, ps.size].min
portrait_count.times { result << ps.shift }
landscape_count = [1, ls.size].min
landscape_count.times { result << ls.shift }
break if ps.empty? && ls.empty?
end
puts result.each_slice(5) { |slice| p slice }
=begin
Outputs:
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["P", "P", "P", "P", "L"]
["L", "L", "L", "L"]
=end
我假设每个对象不仅仅有一个“纵向”或“横向”开关,这就是为什么我将元素按顺序从数组中取出。我猜如果纵向的数量与横向的数量不一致,那么它会将剩余的元素添加到一行中:
arr = %w[portrait landscape portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait portrait landscape landscape]
landscapes, portraits = arr.sort.slice_when { |a, b| a != b }.to_a
p portraits.each_slice(4).flat_map.with_index { |e, i| e << landscapes[i] }.compact
# ["portrait", "portrait", "portrait", "portrait", "landscape", "portrait", "portrait", "portrait", "portrait", "landscape", "portrait", "portrait", "portrait", "portrait", "landscape", "portrait", "portrait", "portrait", "portrait", "portrait"]
这种方法强调计算效率。我计算数组中肖像的数量,并由此计算四人一组的数量以及剩余肖像和风景的数量。然后,我使用这三个量来构造所需的数组,这不需要任何迭代步骤 代码 例子 解释 对于上述arr,步骤如下所示
nbr_portraits = arr.count("portrait")
#=> 17
nbr_landscapes = arr.size - nbr_portraits
#=> 3
groups_of_4_portraits = [nbr_portraits/4, nbr_landscapes].min
#=> 3
nbr_portraits -= 4 * groups_of_4_portraits
#=> 5
nbr_landscapes -= groups_of_4_portraits
#=> 0
b = ["portrait"] * 4
#=> ["portrait", "portrait", "portrait", "portrait"]
c = [*b, "landscape"]
#=> ["portrait", "portrait", "portrait", "portrait", "landscape"]
d = c * groups_of_4_portraits
#=> ["portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape"]
e = ["portrait"] * nbr_portraits
#=> ["portrait", "portrait", "portrait", "portrait", "portrait"]
f = ["landscape"] * nbr_landscapes
#=> []
[*d, *e, *f]
#=> ["portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "portrait"]
快速基准
这里我将上述方法与Sebastian和Keith的解决方案进行比较。结果无法直接比较,因为我们对这个问题的理解不同。基思和我把剩下的肖像画或风景画放在头像的末尾,而塞巴斯蒂安只把剩下的肖像画放在末尾,丢弃了剩下的风景画
require 'fruity'
np = 100
nl = 120
p (arr = [*["portrait"]*np, *["landscape"]*nl].shuffle).size
def sebastian(arr)
landscapes, portraits = arr.sort.slice_when { |a, b| a != b }.to_a
portraits.each_slice(4).flat_map.with_index { |e, i| e << landscapes[i] }.compact
end
def keith(arr)
ps, ls = arr.partition { |element| element == 'portrait' }
result = []
loop do
portrait_count = [4, ps.size].min
portrait_count.times { result << ps.shift }
landscape_count = [1, ls.size].min
landscape_count.times { result << ls.shift }
break if ps.empty? && ls.empty?
end
result
end
compare(
Sebastian: -> { sebastian arr },
Keith: -> { keith arr },
Cary: -> { rearrange arr }
)
Running each test 64 times. Test will take about 1 second.
Cary is faster than Keith by 5x ± 1.0
Keith is similar to Sebastian
缺少一幅肖像,您的预期输出是什么,需要涵盖哪些场景?您可以收集风景和肖像条目的总数,而不是对阵列进行排序,并创建一个新阵列,其中元素位于正确的位置。这使您能够轻松处理没有足够的可用环境的情况,并使您能够轻松控制输出顺序。好的,退步是什么?Keith,我把你的解决方案添加到了基准测试中。我不知道我怎么会错过它。
arr = ["portrait", "landscape", "portrait", "portrait", "portrait", "portrait",
"portrait", "portrait", "portrait", "portrait", "portrait", "portrait",
"portrait", "portrait", "portrait", "portrait", "portrait", "portrait",
"landscape", "landscape"]
rearrange arr
#=> ["portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "portrait"]
rearrange %w| portrait portrait portrait landscape portrait portrait
portrait portrait portrait portrait |
#=> ["portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "portrait"]
rearrange %w| portrait portrait portrait portrait portrait |
#=> ["portrait", "portrait", "portrait", "portrait", "portrait"]
rearrange %w| landscape landscape portrait landscape portrait |
#=> ["portrait", "portrait", "landscape", "landscape", "landscape"]
rearrange %w| landscape landscape landscape landscape |
#=> ["landscape", "landscape", "landscape", "landscape"]
rearrange []
#=> []
nbr_portraits = arr.count("portrait")
#=> 17
nbr_landscapes = arr.size - nbr_portraits
#=> 3
groups_of_4_portraits = [nbr_portraits/4, nbr_landscapes].min
#=> 3
nbr_portraits -= 4 * groups_of_4_portraits
#=> 5
nbr_landscapes -= groups_of_4_portraits
#=> 0
b = ["portrait"] * 4
#=> ["portrait", "portrait", "portrait", "portrait"]
c = [*b, "landscape"]
#=> ["portrait", "portrait", "portrait", "portrait", "landscape"]
d = c * groups_of_4_portraits
#=> ["portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape"]
e = ["portrait"] * nbr_portraits
#=> ["portrait", "portrait", "portrait", "portrait", "portrait"]
f = ["landscape"] * nbr_landscapes
#=> []
[*d, *e, *f]
#=> ["portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "landscape",
# "portrait", "portrait", "portrait", "portrait", "portrait"]
require 'fruity'
np = 100
nl = 120
p (arr = [*["portrait"]*np, *["landscape"]*nl].shuffle).size
def sebastian(arr)
landscapes, portraits = arr.sort.slice_when { |a, b| a != b }.to_a
portraits.each_slice(4).flat_map.with_index { |e, i| e << landscapes[i] }.compact
end
def keith(arr)
ps, ls = arr.partition { |element| element == 'portrait' }
result = []
loop do
portrait_count = [4, ps.size].min
portrait_count.times { result << ps.shift }
landscape_count = [1, ls.size].min
landscape_count.times { result << ls.shift }
break if ps.empty? && ls.empty?
end
result
end
compare(
Sebastian: -> { sebastian arr },
Keith: -> { keith arr },
Cary: -> { rearrange arr }
)
Running each test 64 times. Test will take about 1 second.
Cary is faster than Keith by 5x ± 1.0
Keith is similar to Sebastian