如何测试某个特定元素是否在数组中的另一个特定元素之前?

时间:2017-07-23 19:48:16

标签: arrays ruby dependencies

我遇到了一个问题,即每个字符"a""b""c"等代表的作业列表必须进行排序,因为其中一些作业依赖于其他工作。因此,如果作业"a"取决于"b""b""c"并不依赖于任何作业,则列表'abc'将排序为{ {1}},简单。

我的问题是我想编写一个测试来检查作业是否在它们依赖于输出数组的作业之后。

实施例

如果作业'bac'取决于作业"c",我如何测试"f"之前的"f"

"c"

3 个答案:

答案 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 graphdirected acyclic graph

要获得合适的工作数组,您需要topological sorting,例如使用Kahn's algorithmdepth-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')

enter image description here

您需要检查的是结果数组是否为空:

require 'plexus'

include Plexus
dg = Digraph["c","a", "a","b", "b","a"] 
p dg.topsort
# []

enter image description here

如果它为空,则依赖项中至少有一个循环,并且找不到任何数组。如果数组不为空,则它以正确的顺序包含每个元素。无需进一步检查。