我遇到了一个问题,即每个字符"a"
,"b"
,"c"
等代表的作业列表必须进行排序,因为其中一些作业依赖于其他工作。因此,如果作业"a"
取决于"b"
,"b"
和"c"
并不依赖于任何作业,则列表'abc'
将排序为{ {1}},简单。
我的问题是我想编写一个测试来检查作业是否在它们依赖于输出数组的作业之后。
如果作业'bac'
取决于作业"c"
,我如何测试"f"
之前的"f"
"c"
答案 0 :(得分:2)
Cary Swoveland在评论中已经有了大部分解决方案。这是一个完整的例子,它处理所有情况(没有c,没有f,也没有,错误的顺序,ok)
jobs = %w[a b f c d e]
index_c = jobs.index('c')
index_f = jobs.index('f')
if index_c && index_f && index_c > index_f
puts "Everything is fine"
elsif index_c && index_f
puts "job c is before job f"
elsif !index_c && !index_f
puts "jobs are missing"
elsif !index_c
puts "no job c"
else
puts "no job f"
end
答案 1 :(得分:2)
您可以创建一个包含作业及其依赖关系的哈希值,例如,如果作业c
取决于f
,而b
取决于a
,则在您的示例中,然后:
hash = {c: 'f', b: 'a'}
因此,通过哈希,您可以使用map
来获得"普通"你在数组中检查数组中散列值的索引是否小于数组中散列键的索引(到字符串)的数组,如果是,则添加true
,然后检查其中的所有值数组,都必须是true
:
array = ['a', 'b', 'f', 'c', 'd', 'e']
result = hash.map{|k,v| array.index(v) < array.index(k.to_s)}
p result.all?{|e| e} # => true
因此,使用Minitest,您可以测试result.all?{|e| e}.eql?
等于true
:
require 'minitest/autorun'
class Test < Minitest::Test
def test_a_job_is_before_its_dependency
hash = {c: 'f', b: 'a'}
array = ['a', 'b', 'f', 'c', 'd', 'e']
result = hash.map{|k,v| array.index(v) < array.index(k.to_s)}.all?{|e| e}
assert result.equal? true
end
end
答案 2 :(得分:2)
此问题的最佳数据格式为dependency graph或directed acyclic graph。
要获得合适的工作数组,您需要topological sorting,例如使用Kahn's algorithm或depth-first search。
Plexus
gem提供拓扑排序。
require 'plexus'
include Plexus
dg = Digraph["a","b", "a","f", "f","c", "f","d", "d","e", "b","f"]
p dg.topsort
# ["a", "b", "f", "d", "e", "c"]
require 'plexus/dot'
dg.write_to_graphic_file('png','visualize')
您需要检查的是结果数组是否为空:
require 'plexus'
include Plexus
dg = Digraph["c","a", "a","b", "b","a"]
p dg.topsort
# []
如果它为空,则依赖项中至少有一个循环,并且找不到任何数组。如果数组不为空,则它以正确的顺序包含每个元素。无需进一步检查。