【问题标题】:Generate a filtered subset of repeated permutations of an array of objects (with given length k)生成对象数组的重复排列的过滤子集(给定长度 k)
【发布时间】:2017-01-30 04:16:06
【问题描述】:

我是 Ruby 的新手。我需要根据长度生成对象的所有组合。

例如array = [obj1, obj2, obj3]length = 2,则组合为:

[
  [obj1, obj1],
  [obj1, obj2],
  [obj1, obj3],
  # ...
  [obj3, obj3]
]

我知道我可以使用repeated_permutation 方法来解决这个问题,但我还需要能够过滤一些排列。例如,要过滤掉两个相同对象一个接一个的排列,即像这样[obj1, obj1]

【问题讨论】:

  • { obj1, obj2, obj3 } 不是 Ruby 中的有效对象
  • @AndreyDeineko,我知道,我只是用数学符号表示集合。
  • ackacky,set的定义有两个问题。 @Andrey 提到了一个。第二个是obj1(和其他)要么是具有未知值的变量,要么是未指定的方法。出于问题的目的,您应该将它们设为文字、字符串或符号。你需要写,比如说,require 'set'; set = [:obj1, :obj2, :obj3].to_set #=> #<Set: {:obj1, :obj2, :obj3}>(或Set.new [:obj1, :obj2, :obj3])。你需要编辑来解决这个问题。
  • @CarySwoveland,如果问题不清楚,我很抱歉,但排列生成问题本身被描述为不是红宝石问题。这只是对问题的抽象描述。
  • 请不要在发布 cmets 或答案后更改问题,但如果您这样做,请注意您已在编辑中这样做。无声的更改会导致 cmets 和答案不正确或无意义。

标签: ruby algorithm permutation


【解决方案1】:

如果您只需要删除任何相同的 obj 对,您可以简单地使用 permutation 方法。

arr = [1,2,3]
arr.permutation(2).to_a

#=>  [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]

【讨论】:

    【解决方案2】:

    给定一个任意输入数组:

    a = [1, 2, 3, 3, 4]
    

    如果您希望生成唯一的排列,那么您可以简单地这样做:

    a.uniq.permutation(2)
    

    (如果您知道初始数组包含唯一元素,则不需要uniq!)

    但是,作为更通用的解决方案,您必须这样做:

    a.repeated_permutation(2).reject { |permutation| ** FILTER RULE GOES HERE ** }
    

    例如,如果您希望过滤所有没有两个连续重复值的结果,那么您可以这样做:

    a.repeated_permutation(2).reject do |permutation|
      permutation.each_cons(2).any? {|x, y| x == y}
    end
    

    把这个发挥到极致,这里有一个通用的方法:

    def filtered_permutations(array, length)
      array.repeated_permutation(length).reject{|permutation| yield(permutation)}
    end
    
    # Or, if you prefer:
    
    def filtered_permutations(array, length, &block)
      array.repeated_permutation(length).reject(&block)
    end
    
    # Usage:
    
    a = [1, 2, 3, 3, 4]
    
    filtered_permutations(a, 2) {|permutation| permutation.each_cons(2).any? {|x, y| x == y} }
    
    # Or, if you prefer:
    filtered_permutations(a, 2) {|permutation| permutation.each_cons(2).any? {|consecutive| consecutive.uniq.one?} }
    

    【讨论】:

      【解决方案3】:

      传递一个执行“过滤”的块。因此,要删除那些具有相同元素的元素:

      a = [1,2,3]
      a.repeated_permutation(2).reject { |permutation| permutation.uniq.one? }
      #=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
      

      【讨论】:

      • 所以如果length=3,[1, 2, 1] 应该是有效的,但permutation.uniq.one? 将返回false
      • 它应该返回 false,reject 方法会删除块返回 true 的任何元素。所以[1,2,1]不会被拒绝。
      • @ackacky.bashmacchckin 它将返回false,因为您要求如果都一样则拒绝
      • 这是通用过滤方法的正确答案。但是,对于仅过滤“重复值”的特殊情况,您应该只使用Array#permutation - 然后不需要任何Array#reject 的东西。
      • 您在问题中完全没有说明这一点。基于此信息,我可以在下面提供答案 - 但请尝试在未来更好地解释要求。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 1970-01-01
      相关资源
      最近更新 更多