所以我试图测试一周工作日名称数组是否正确排序,无论它从何处开始如此
[Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday] => true
[Thursday, Friday, Saturday, Sunday, Monday, Tuesday, Wednesday] => true
[Monday, Thursday, Tuesday, Wednesday, Sunday, Friday, Saturday] => false
这是我到目前为止所做的:
module Enumerable
def sorted_by?
each_cons(2).all? { |a, b| ((yield a) <=> (yield b)) <= 0 }
end
end
和
correct_week_days = {
:monday => 0,
:tuesday => 1,
:wednesday => 2,
:thursday => 3,
:friday => 4,
:saturday => 5,
:sunday => 6
}
test_week_days_array.sorted_by? { |k, v| correct_week_days[k.to_sym] }
在未排序的工作日字符串数组中返回true。我知道这种方法存在缺陷,因为它不能解释循环。
修改
我应该为我测试的数据提供一个实际的例子
['monday', 'thursday', 'tuesday', 'wednesday', 'sunday', 'friday', 'saturday']
这将是一个失败的例子。
['wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'monday', 'tuesday']
这会过去。
答案 0 :(得分:4)
一种简单的双线算法,(可选)适用于包含少于七天的输入。
了解日子:
days = %w(monday tuesday wednesday thursday friday saturday sunday)
# => ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
将数组加倍,使其包含所有可能的有效子数组:
days *= 2
# => ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
鉴于您的输入案例......
case1 = %w(monday tuesday wednesday thursday friday saturday sunday)
case2 = %w(thursday friday saturday sunday monday tuesday wednesday)
case3 = %w(monday thursday tuesday wednesday sunday friday saturday)
case4 = %w(wednesday thursday friday saturday sunday monday tuesday)
对于每个输入案例,请查看days
数组中是否有与您的输入匹配的slice of consecutive elements:
days.each_cons(case1.length).include?(case1) # true
days.each_cons(case2.length).include?(case2) # true
days.each_cons(case3.length).include?(case3) # false
days.each_cons(case4.length).include?(case4) # true
总而言之,这是一个双线解决方案:
def days_in_order?(days)
search_list = %w(monday tuesday wednesday thursday friday saturday sunday) * 2
search_list.each_cons(days.length).include?(days)
end
您需要处理输入的大小写不匹配的情况('monday'
vs 'Monday'
),但这是一个微不足道的扩展。如果您希望此选项仅接受七天的输入数组,请将each_cons(days.length)
更改为each_cons(7)
。
答案 1 :(得分:2)
某些功能方法怎么样?考虑下面的代码(请注意它可以用更紧凑的方式编写,为了便于阅读,我留下了大if-than-else
):
DAYS = [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday]
def days_sorted_ok?(weekdays)
if weekdays.empty? || weekdays.count == 1
# only one day, so it is sorted well
return true
else
# true, if the next day (weekdays[1]) is the next on the DAYS list
if weekdays[1] == DAYS[(DAYS.index(weekdays[0]) + 1) % DAYS.count]
if weekdays.count == 2
# only two days in the table, so the whole thing is sorted well
return true
else
# check if the tail of the array is sorted well
days_sorted_ok?(weekdays[1..-1])
end
else
# second element is not a next weekday
return false
end
end
end
这是一种反复出现的方法。首先,它检查数组是否为空或仅包含一个元素。在这种情况下,它将它视为一种良好的排序方式。在另一种情况下,它检查列表的第二个元素是否是DAYS
列表的下一个(使用模数,以循环工作日)。如果是,并且列表只包含2个元素,则表示它排序良好。在另一种情况下,它将在列表的其余部分中搜索递归。
以下几项测试:
days_sorted_ok? DAYS
#=> true
days_sorted_ok? [:tuesday, :wednesday, :thursday]
#=> true
days_sorted_ok? [:monday, :tuesday, :wednesday, :thursday, :friday, :sunday, :sunday]
#=> false
days_sorted_ok? [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday, :monday, :sunday]
#=> false
答案 2 :(得分:1)
def same_order?(arr1, arr2)
raise 'Not same array' unless arr1.sort == arr2.sort
arr1.length.times do
arr1 = arr1.rotate
return true if arr1 == arr2
end
return false
end
correct_order = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
a = ['wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'monday', 'tuesday']
b = ['monday', 'thursday', 'tuesday', 'wednesday', 'sunday', 'friday', 'saturday']
p same_order?(correct_order, a) #=> true
p same_order?(correct_order, b) #=> false
答案 3 :(得分:0)
我的解决方案重新排序测试中的数组,并与正确排序的数组进行比较(以及一些数据管理)
def test a
# deal with an array of symbols or strings
a = a.map do |day| day.downcase.to_sym end
# make sure we at least have a monday in the array so we don't get stuck
if a.include? :monday
# reorder array so that monday is the first element
while a.first != :monday
a << a.shift
end
end
# does it match an ideal ordered array?
a == [:monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday]
end
答案 4 :(得分:0)
另一种方法是使用方法Array#rotate!(或rotate
)。
我假设要测试的数组包含一周中七天的名称,大写,而没有别的。我们只是检查订单是否正确。
首先,如果读者不熟悉使用%w
构造字符串数组,那么这里有一个例子:
%w{ Monday Tuesday Wednesday Thursday Friday Saturday Sunday }
#=> ["Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"]
<强>代码强>
def dow_sorted?(arr)
%w{ Monday Tuesday Wednesday Thursday Friday Saturday Sunday }
.rotate!(-arr.index('Monday')) == arr
end
<强>实施例强>
dow_sorted? %w{ Monday Tuesday Wednesday Thursday Friday Saturday Sunday }
#=> true
dow_sorted? %w{ Thursday Friday Saturday Sunday Monday Tuesday Wednesday }
#=> true
dow_sorted? %w{ Monday Thursday Tuesday Wednesday Sunday Friday Saturday }
#=> false
dow_sorted? %w{ Friday Saturday Sunday Monday Wednesday Tuesday Thursday }
#=> false
<强>解释强>
最后一个例子:
arr = %w{ Friday Saturday Sunday Monday Wednesday Tuesday Thursday }
#=> ["Friday", "Saturday", "Sunday", "Monday",
# "Wednesday", "Tuesday", "Thursday"]
ord = %w{ Monday Tuesday Wednesday Thursday Friday Saturday Sunday }
#=> ["Monday", "Tuesday", "Wednesday", "Thursday",
# "Friday", "Saturday", "Sunday"]
n = arr.index('Monday')
#=> 3
a = ord.rotate(-3)
#=> ["Friday", "Saturday", "Sunday", "Monday",
# "Tuesday", "Wednesday", "Thursday"]
a == arr
#=> false
答案 5 :(得分:0)
这是另一种解决方案,只是为了将更多算法收集在一起。简而言之 - 你找到一个星期一的位置并将它和所有连续元素移动到数组的开头(实际上它就像使用rotate
但没有rotate
)然后进行比较使用正确排序的列表。
days = %w(monday tuesday wednesday thursday friday saturday sunday)
case1 = %w(monday tuesday wednesday thursday friday saturday sunday)
case2 = %w(thursday friday saturday sunday monday tuesday wednesday)
case3 = %w(monday thursday tuesday wednesday sunday friday saturday)
case4 = %w(wednesday thursday friday saturday sunday monday tuesday)
def days_in_order?(days)
monday_index = days.index('monday')
search_list = %w(monday tuesday wednesday thursday friday saturday sunday)
search_list == days.slice(monday_index, days.size) | days[0...monday_index]
end
days_in_order?(case1) # true
days_in_order?(case2) # true
days_in_order?(case3) # false
days_in_order?(case4) # true
仅供参考,这个算法比@meagar的算法更快(我的机器上的约4s vs~6s,对于case3的1000000次迭代),但是他的解决方案更容易阅读,我认为在这种情况下性能不是目标: - )
PS。我在days.size
而不是days.slice(monday_index, days.size)
中写了days.size - monday_index
,因为实际上并不需要它,因为目标只是达到或超过数组的大小。