0

我定义了一个类My_Class。它的一个属性是type:假设"A","B""C"my_ary我创建了的实例数组My_Class,并根据日期、时间和其他实例数据对其进行排序。项目按特定顺序排列。我想遍历数组,并且对于 type 的每个对象,找到下一个未与类型项配对的"A"类型的顺序项,然后将这两个项配对。被配对的项目必须是下一个后续向上配对的类型对象。"B""A""B"

我可以使用数组上的循环来做到这一点:

(0...my_ary.length) do |idx|
   if (my_ary[idx].type=="A") then
      ...iterate array from idx+1 and find next available type "B", 
         "pair" it to item at idx, and make paired item unavailable 
         for further matching...
   end
end

配对的数组元素 0..6 。每一行都是一个 My_Class 对象,而不是一个 Hash。我对每个数组元素使用 BRACKET 和类似哈希的键值表示法,因为我不知道如何正确表示对象数组。

idx   data
0     [type:'A' , pairedto:nil , pairedby:nil , '1/1/2000' , ...other data...]
1     [type:'C' , pairedto:nil , pairedby:nil , '1/2/2000' , ...other data...]
2     [type:'A' , pairedto:nil , pairedby:nil , '1/5/2000' , ...other data...]
3     [type:'B' , pairedto:nil , pairedby:nil , '1/5/2000' , ...other data...]
4     [type:'A' , pairedto:nil , pairedby:nil , '1/6/2000' , ...other data...]
5     [type:'B' , pairedto:nil , pairedby:nil , '1/6/2000' , ...other data...]
6     [type:'B' , pairedto:nil , pairedby:nil , '1/8/2000' , ...other data...]

配对

idx   data
0     [type:'A' , pairedto:3 , pairedby:nil , '1/1/2000' , ...other data...]
1     [type:'C' , pairedto:nil , pairedby:nil , '1/2/2000' , ...other data...]
2     [type:'A' , pairedto:5 , pairedby:nil , '1/5/2000' , ...other data...]
3     [type:'B' , pairedto:nil , pairedby:0 , '1/5/2000' , ...other data...]
4     [type:'A' , pairedto:6 , pairedby:nil , '1/6/2000' , ...other data...]
5     [type:'B' , pairedto:nil , pairedby:2 , '1/6/2000' , ...other data...]
6     [type:'B' , pairedto:nil , pairedby:4 , '1/8/2000' , ...other data...]

我想将部分或全部迭代、限定、搜索和配对逻辑移动到类定义中。 我想强调的是,数据和操作并不那么重要——我想做的是发现以 ruby​​ 为中心或非传统的方法来迭代和分类对象集合。完成这项工作的实际代码是无关紧要的。 对于这个问题,我看到了两个机会:

一世。将数组迭代器保留在主程序中,但扩展类以允许对象搜索数组中的剩余对象: 对于每个类型"A"项,找到下一个可用类型"B",并将其自身与该对象配对:

    (0...my_ary.length) do |idx| 
      if (my_ary[idx].type=="A") then my_ary[idx].pair_yourself(y_ary,idx) end 
    end 

ii. 将主程序数组迭代器移动到类方法中,并结合选项 1。让类处理所有事情。主程序说:

    My_Class.go_pair_all_items_in_array(my_ary)

问题:

  1. 在方法 2 中,My_Class负责迭代未知形状和形式的数组是否公平?假设传入的任何数组都是My_Class项目或派生自项目。我很确定 Class 方法有一种方法可以确定传入的数组是否包含从自身派生的元素。
  2. 还有其他非传统方法可以做到这一点吗?我知道我可以为数组创建一个类并让它处理列表迭代,但这似乎还不足以成为一个心理挑战。
4

1 回答 1

1

我的猜测是您是 Java 或 C++ 程序员,因为您的思维是以类为中心的。

Ruby 方式是鸭式打字。要使分类配对起作用,您只需要知道列表中的项目是否respond_to?type方法和pairedby=. 将这个操作作为数组的混合实现是非常标准的 Ruby。

除非需要访问内部函数(即pair_with_next.

一个原因:通过拆分函数,当 O(n) 很容易获得时,你几乎注定要获得 O(n^2) 的性能。过一关。保留一个 A 索引队列。当您看到 B 时,从队列中删除头索引。那是与当前 B 匹配的 A。继续直到完成。如果队列为空,则为匹配的 A 分配 nil。Ruby 数组很容易实现队列。

混合看起来像:

class Array
  def pairable_by_type?
    all? {|i| [:type, :pairedby=].all?{|t| i.respond_to? t } }
  end

  def pair_by_type(a='A', b='B')
    q = []
    each_with_index do |item, i|
      item.pairedby = nil  # clear previous pairing
      case item.type
        when a
          q << i
        when b
          item.pairedby = q.shift
      end
    end
  end
end

我没有测试过这个,但它应该很接近。你只会说my_ary.pair_by_type完成工作。也会告诉你这my_ary.pairable_by_type?是可行的。

这种混合将配对功能添加到应用程序中的所有阵列。有些人可能会觉得这很反感。为了避免它,

class Array
  def self.new_pairable
    ary = []  
    def ary.pair_by_type(a='A', b='B')
      q = []
      each_with_index do |item, i|
        item.pairedby = nil  # clear previous pairing
        case item.type
          when a
            q << i
          when b
            item.pairedby = q.shift
        end
      end
    end
    ary
  end
end

现在你可以说my_ary = Array.new_pairable然后my_ary.pair_by_type。但通常创建的数组不会有该pair_by_type方法。

于 2013-09-12T00:47:03.567 回答