简体   繁体   English

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

[英]Find a unique element in a compound array

I am trying to solve a problem where I need to find the airport code in an array of arrays of that represents the starting point of a multi-city flight plan. 我正在尝试解决一个问题,该问题需要我在一个数组的数组中找到一个代表多城市飞行计划起点的机场代码。 For example: Given an array [['LAX', 'BWI'], ['BOS', 'SEA'], ['HNL', 'LAX'], ['SEA', 'HNL']] where the first index of each sub array is the departing airport and the second is the destination airport, I need to find the index point where the flight originates, in this case the method would return 1 to represent ['BOS', 'SEA']. 例如:给定数组[['LAX','BWI'],['BOS','SEA'],['HNL','LAX'],['SEA','HNL']],其中第一个每个子数组的索引是出发机场,第二个是目的地机场,我需要找到航班始发的索引点,在这种情况下,该方法将返回1来表示['BOS','SEA']。

This code does not work and always returns the last element in the array 此代码不起作用,并且始终返回数组中的最后一个元素

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

I see what you're attempting. 我知道您在尝试什么。 The originating airport would be the only one included in a 0 index of a sub array but not a 1 index of any sub array. 始发机场将是唯一包含在子数组的0索引中的机场,而不是任何子数组的1索引中包括的机场。

However, in you're solution, you are comparing each combination of 2 sub arrays (including a sub array and itself, by the way...), and then returning the index of list if a[0] != b[1] is ever true for sub array a . 然而,在你的解决方案,你是比较2个阵列的每个组合(包括一个子阵列和本身,顺便...),然后返回的索引list ,如果a[0] != b[1]对于子数组a永远是正确a This is returning too many results, and you'll always end up returning the last index. 这将返回太多结果,并且您将总是最终返回最后一个索引。 For example, 'SEA', the 0 index of the 3rd sub array, does not equal 'BWI', the 1 index of the 0 sub array, so your start_point now equals 3. 例如,第三个子数组的0索引'SEA'不等于0子数组的1索引'BWI',因此start_point现在等于3。

I won't do all of your work for you :), but let me suggest this: When you're going through your iterations, keep track of which sub arrays' index 0 ever equals a different sub array's index 1. Your answer will be the only one not included in this list. 我不会为您完成所有工作:),但我建议您这样做:在进行迭代时,请跟踪哪个子数组的索引0等于另一个子数组的索引1。是此列表中未包括的唯一一个。

Edit: Continue to work through my above suggestion for good practice, but here's a real quick and short solution: 编辑:继续按照我的上述建议进行最佳实践,但这是一个真正的快速而简短的解决方案:

def find_start_point(list)
  list.each_with_index do |sub, idx|
    return idx if list.flatten.count(sub[0]) == 1
  end
end

This works by returning the index of the sub array with an index 0 where there are no other occurrences of that airport (by flattening the entire array and using #count ) 这可以通过返回子索引的索引为0的方式来实现,在该索引中没有该机场的其他地方(通过展平整个数组并使用#count

sorry i, have no enough time to explain my code - but i think nothing is such difficult not to figure out what is happening :) 抱歉,我没有足够的时间来解释我的代码-但我认为没有弄清楚发生了什么事就这么困难:)

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

Building on dwenzel's idea: 基于dwenzel的想法:

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

departures, arrivals = airports.transpose

first_departure_index = departures.index{|dep| !arrivals.include?(dep)}
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

If you think with Ruby's syntax in mind, just take a transpose and take out all arrivals from departures. 如果您考虑了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 HTH

You could do this: 您可以这样做:

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"

This could instead be written using Array#transpose (as has been done in other answers) or Enumerable#zip since: 而是可以使用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"] 

My main reason for answering, however, is to make a plug for the method Array#difference , which I'd like to see in some future Ruby version. 但是,我回答的主要原因是为Array#difference方法创建一个插件,我希望在将来的某些Ruby版本中看到它。 It is defined here . 在这里定义。

With it, we can write: 有了它,我们可以编写:

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

Note that: 注意:

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

contains all airports that appear more than once in the legs; 包含所有出现不止一次的机场; that is, all all the "intermediate" airports. 也就是说,所有“中间”机场。

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

arrivals = trips.map(&:last)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM