【问题标题】:Combine arrays and preserve ordering - but prioritize one array's ordering over another组合数组并保留顺序 - 但优先考虑一个数组的顺序而不是另一个
【发布时间】:2016-08-15 00:41:25
【问题描述】:

假设我有两个数组:

Arr1 = ["1-a", "1-b", "1-c"]
Arr2 = ["2-a", "2-b", "2-c"]

我知道如何将它们组合成一个数组,保持它们的顺序:

  Arr1.zip(Arr2).flatten(1)
  # => ["1-a", "2-a", "1-b", "2-b", "1-c", "2-c"]

在本例中,我认为 Arr1 的“优先级”高于 Arr2,因为“1-a”出现在“2-a”之前,“1-c”出现在“2-c”之前。

如果 Arr2 被“优先化”,会发生以下情况:

Arr2.zip(Arr1).flatten(1)
# => ["2-a", "1-a", "2-b", "1-b", "2-c", "1-c"]

在这些示例中,“优先级”是一种二元状态。但是如果我想使用小数呢?这就是我想要发生的事情:

y axis: percentage of added nodes that are Arr1
x axis: percent completion of Arr2 iteration

   100% |                     X
        |           
   75%  |                X
        |
   50%  |           X
        |
   25%  |       X
        |
    0%  |  X        
        ------------------------- 
           0%  25%  50%  75%  100%

【问题讨论】:

    标签: arrays ruby algorithm


    【解决方案1】:

    这是我写的

    class Array
    
      # helper method to help with testing
      def mean
        map(&:to_f).reduce(&:+) / length.to_f
      end
    
      # target is another array
      # priority is a number between 0 and 1
      #   if 0, then target will not be merged in at all
      #   if 1, then the result will be ~50% composed of target
      # returns array with the same length as self
      # Note that the result will not contain all of self.concat(target)
    
      def priority_merge(priority, target)
        # clone the arrays to avoid side-effects
        arr1, arr2 = [self, target].map(&:clone)
        # get the original length to determine the results length
        arr1_len = arr1.length.to_f
        # convert priority to float
        priority = priority.to_f
        # initialize a results set
        results = []
        # populate the results set
        arr1_len.to_i.times do |arr1_idx|
          # determine the percentage completed through iteration
          pct_iterated = arr1_idx.to_f / arr1_len.to_f
          # calculate per-run likelihood of favoring target
          per_run_priority = pct_iterated * priority
          # conclusively determine which array this iteration will pull from
          num_true_cases = (100.0 * per_run_priority).to_i
          cases = num_true_cases.times.map { true }.concat((100 - num_true_cases).times.map { false })
          priority_run_result = cases.sample
          # push from arr2 if the priority run result is true, otherwise push from arr1
          elem_to_push = (priority_run_result ? arr2 : arr1).shift
          # if arr2 is empty, push from arr1 instead 
          results << elem_to_push || arr1.shift
        end
        results
      end
    end
    

    并测试它

    a1 = 50.times.map { 1 }
    a2 = 50.times.map { 2 }
    
    puts "MERGE CASE 1"
    result = 50.times.map do
      result = a1.priority_merge(1.0, a2)
      result.select { |item| item == 2 }.count.to_f / a1.length.to_f
    end
    puts result.mean
    # => is around 50%
    
    puts "MERGE CASE 0.5"
    result = 50.times.map do
      result = a1.priority_merge(0.5, a2)
      result.select { |item| item == 2 }.count.to_f / a1.length.to_f
    end
    puts result.mean
    # => is around 25%
    puts "MERGE CASE 0"
    result = 50.times.map do
      result = a1.priority_merge(0.0, a2)
      result.select { |item| item == 2 }.count / a1.length.to_f
    end
    puts result.mean
    # => is 0%
    

    【讨论】:

      猜你喜欢
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-19
      • 1970-01-01
      相关资源
      最近更新 更多