在复合数组中查找唯一元素

时间:2015-04-11 23:44:28

标签: ruby arrays

我正在尝试解决一个问题,我需要在一组阵列中找到机场代码,这代表了多城市飞行计划的起点。 例如:给定一个阵列[[' LAX',' BWI'],[' BOS',' SEA'],[&# 39; HNL',' LAX'],[' SEA'' HNL']]其中每个子数组的第一个索引是 离开机场,第二个是目的地机场,我需要找到航班起点的索引点,在这种情况下,该方法将返回1代表[' BOS',' SEA' ]。

此代码不起作用,并始终返回数组中的最后一个元素

def find_start_point(list)
  start_point = nil
  list.each do |a|
    list.each do |b|
      if a[0] != b[1]
        start_point = list.index(a)
      end
    end
  end
  start_point
end

7 个答案:

答案 0 :(得分:1)

我看到你在尝试什么。原始机场将是唯一包含在子数组的0索引中但不包含任何子数组的1索引的机场。

但是,在您的解决方案中,您正在比较2个子数组的每个组合(包括子数组和自身,顺便说一下......),然后返回list if {{ 1}}对于子数组a[0] != b[1]来说是真的。这会返回太多结果,并且您总是会返回最后一个索引。例如,'SEA',第3个子数组的0索引,不等于'BWI',即0子数组的1个索引,因此您的a现在等于3。

我不会为你完成所有的工作:),但是让我建议:当你进行迭代时,跟踪哪个子数组的索引0等于不同的子数组的索引1。您的答案将是唯一未包含在此列表中的答案。

修改:继续完成我的上述建议以获得良好实践,但这是一个真正快速而简短的解决方案:

start_point

这是通过返回索引为0的子数组的索引来实现的,其中没有其他事件发生(通过展平整个数组并使用def find_start_point(list) list.each_with_index do |sub, idx| return idx if list.flatten.count(sub[0]) == 1 end end

答案 1 :(得分:0)

抱歉,我没有足够的时间来解释我的代码 - 但我认为没有什么比这更难以弄清楚发生了什么:)

here is the working example

def find_start_point(list)
    start = []
    finish = []

    list.each do |l|
        start.push(l[0])
        finish.push(l[1])
    end

    start.each do |st|
        if !finish.include? st
            return start.index(st)
        end
    end

end

答案 2 :(得分:0)

以dwenzel的想法为基础:

airports = [['LAX', 'BWI'], ['BOS', 'SEA'], ['HNL', 'LAX'], ['SEA', 'HNL']]

departures, arrivals = airports.transpose

first_departure_index = departures.index{|dep| !arrivals.include?(dep)}

答案 3 :(得分:0)

def find_start(arr)
  flat = arr.flatten
  first, second = flat.reject { |val| flat.count(val) > 1}
  start_city = if flat.index(first) % 2 == 0 #if index of first is even
                 first
               else
                 second
               end
  arr.find { |pair| pair[0] == start_city }
end

答案 4 :(得分:0)

如果您考虑使用Ruby的语法,只需进行转置并从出发处取出所有到来的人。

def flight_origin(arr)
  plan = arr.transpose
  plan[0].index((plan[0] - plan[1])[0])
end

flight_origin([['LAX', 'BWI'], ['BOS', 'SEA'], ['HNL', 'LAX'], ['SEA', 'HNL']]) # => 1

HTH

答案 5 :(得分:0)

你可以这样做:

legs = [['LAX', 'BWI'], ['BOS', 'SEA'], ['HNL', 'LAX'], ['SEA', 'HNL']]

airports = legs.flatten 
  #=> ["LAX", "BWI", "BOS", "SEA", "HNL", "LAX", "SEA", "HNL"] 
legs.map(&:first).find { |ap| airports.count(ap) == 1 }
  #=> "BOS"

这可以使用Array#transpose(正如在其他答案中所做的那样)或Enumerable#zip来编写,因为:

legs.map(&:first)
  #=> ["LAX", "BOS", "HNL", "SEA"] 
legs.transpose.first
  #=> ["LAX", "BOS", "HNL", "SEA"] 
legs.first.zip(*legs[1..-1]).first
  #=> ["LAX", "BOS", "HNL", "SEA"] 

然而,我回答的主要原因是为方法Array#difference创建一个插件,我希望在将来的Ruby版本中看到它。它定义为here

有了它,我们可以写:

airports = legs.flatten 
  #=> ["LAX", "BWI", "BOS", "SEA", "HNL", "LAX", "SEA", "HNL"] 
(legs.map(&:first) - airports.difference(airports.uniq)).first
  #=> "BOS" 

请注意:

airports.difference(airports.uniq)
  #=> ["LAX", "SEA", "HNL"]

包含腿部出现不止一次的所有机场;也就是说,所有“中间”机场。

答案 6 :(得分:0)

trips = [['LAX', 'BWI'], ['BOS', 'SEA'], ['HNL', 'LAX'], ['SEA', 'HNL']]

arrivals = trips.map(&:last)

p trips.find{|fligth| ! arrivals.include? fligth[0] } #=> ["BOS", "SEA"]