source

한 배열에 다른 배열의 모든 요소가 포함되어 있는지 확인하는 방법

manycodes 2023. 5. 26. 21:11
반응형

한 배열에 다른 배열의 모든 요소가 포함되어 있는지 확인하는 방법

주어진:

a1 = [5, 1, 6, 14, 2, 8]

다음의 모든 요소가 포함되어 있는지 확인하고 싶습니다.

a2 = [2, 6, 15]

이 경우 결과는 다음과 같습니다.false.

이러한 어레이 포함을 식별할 수 있는 내장 Ruby/Rails 방법이 있습니까?

이를 구현하는 한 가지 방법은 다음과 같습니다.

a2.index{ |x| !a1.include?(x) }.nil?

더 좋고, 더 읽기 쉬운 방법이 있을까요?

a = [5, 1, 6, 14, 2, 8]
b = [2, 6, 15]

a - b
# => [5, 1, 14, 8]

b - a
# => [15]

(b - a).empty?
# => false

아마도 이것은 읽기가 더 쉬울 것입니다.

a2.all? { |e| a1.include?(e) }

배열 교차를 사용할 수도 있습니다.

(a1 & a2).size == a1.size

참고:size여기서는 속도를 위해 사용되며, 다음 작업도 수행할 수 있습니다(예:

(a1 & a2) == a1

하지만 저는 첫 번째가 더 읽기 쉽다고 생각합니다.이 3개는 일반 루비(레일이 아님)입니다.

이는 다음을 수행하여 달성할 수 있습니다.

(a2 & a1) == a2

이렇게 하면 두 배열의 교차점이 생성되어 모든 요소가 반환됩니다.a2에도 있는 것들a1결과가 다음과 같을 경우a2모든 요소가 에 포함되어 있는지 확인할 수 있습니다.a1.

이 접근 방식은 다음의 모든 요소에 해당하는 경우에만 작동합니다.a2애당초 서로 다릅니다.중복이 있는 경우 이 접근 방식은 실패합니다.Tempos에서 온 것은 여전히 작동하므로, 저는 진심으로 그의 접근법을 추천합니다(또한 아마도 더 빠를 것입니다).

중복 요소가 없거나 요소에 관심이 없는 경우 Set 클래스를 사용할 수 있습니다.

a1 = Set.new [5, 1, 6, 14, 2, 8]
a2 = Set.new [2, 6, 15]
a1.subset?(a2)
=> false

이것이 사용하는 배경에는

all? { |o| set.include?(o) }

배열 클래스에 원숭이 패치를 적용할 수 있습니다.

class Array
    def contains_all?(ary)
        ary.uniq.all? { |x| count(x) >= ary.count(x) }
    end
end

시험

irb(main):131:0> %w[a b c c].contains_all? %w[a b c]
=> true
irb(main):132:0> %w[a b c c].contains_all? %w[a b c c]
=> true
irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c]
=> false
irb(main):134:0> %w[a b c c].contains_all? %w[a]
=> true
irb(main):135:0> %w[a b c c].contains_all? %w[x]
=> false
irb(main):136:0> %w[a b c c].contains_all? %w[]
=> true
irb(main):137:0> %w[a b c d].contains_all? %w[d c h]
=> false
irb(main):138:0> %w[a b c d].contains_all? %w[d b c]
=> true

물론 이 방법은 표준 단독 방법으로 작성할 수 있습니다.

def contains_all?(a,b)
    b.uniq.all? { |x| a.count(x) >= b.count(x) }
end

그리고 당신은 그것을 다음과 같이 호출할 수 있습니다.

contains_all?(%w[a b c c], %w[c c c])

실제로 프로파일링 후 다음 버전이 훨씬 빠르고 코드가 더 짧습니다.

def contains_all?(a,b)
    b.all? { |x| a.count(x) >= b.count(x) }
end

(a1 - a2) 또는 (a1 및 a2)를 기반으로 한 대부분의 답변은 두 배열에 중복 요소가 있는 경우 작동하지 않습니다.저는 단어의 모든 문자(열로 분할)가 (스크래블 등의) 문자 집합의 일부인지 확인하는 방법을 찾아 여기에 도착했습니다.이 답변들 중 어느 것도 효과가 없었지만, 이 답변은 다음과 같습니다.

def contains_all?(a1, a2)
  try = a1.chars.all? do |letter|
    a1.count(letter) <= a2.count(letter)
  end
  return try
end

어레이 크기에 따라 효율적인 알고리즘 O(n log n)를 고려할 수 있습니다.

def equal_a(a1, a2)
  a1sorted = a1.sort
  a2sorted = a2.sort
  return false if a1.length != a2.length
  0.upto(a1.length - 1) do 
    |i| return false if a1sorted[i] != a2sorted[i]
  end
end

정렬 비용 O(n log n) 및 각 쌍 확인 비용 O(n)이므로 이 알고리즘은 O(n log n)입니다.다른 알고리즘은 정렬되지 않은 어레이를 사용하여 (점근적으로) 더 빠를 수 없습니다.

하나의 배열을 찾으려 할 때 이 게시물로 향했습니다.["a", "b", "c"]다른 배열을 포함했습니다.["a", "b"]나의 경우 동일한 주문이 질문에 대한 추가적인 요구 사항이었습니다.

다음은 이러한 추가 요구사항이 있는 모든 사용자를 위한 솔루션(O(n) 복잡성이라고 생각됨)입니다.

def array_includes_array(array_to_inspect, array_to_search_for)
  inspectLength = array_to_inspect.length
  searchLength = array_to_search_for.length

  if searchLength == 0 then
    return true
  end

  if searchLength > inspectLength then
    return false
  end

  buffer = []

  for i in 0..inspectLength
    buffer.push(array_to_inspect[i])

    bufferLastIndex = buffer.length - 1
    if(buffer[bufferLastIndex] != array_to_search_for[bufferLastIndex]) then
      buffer.clear
      next
    end

    if(buffer.length == searchLength) then
      return true
    end
  end

  return false
end

이렇게 하면 테스트 결과가 생성됩니다.

puts "1: #{array_includes_array(["a", "b", "c"], ["b", "c"])}" # true
puts "2: #{array_includes_array(["a", "b", "c"], ["a", "b"])}" # true
puts "3: #{array_includes_array(["a", "b", "c"], ["b", "b"])}" # false
puts "4: #{array_includes_array(["a", "b", "c"], ["c", "b", "a"])}" # false
puts "5: #{array_includes_array(["a", "b", "c"], [])}" # true
puts "6: #{array_includes_array([], ["a"])}" # false
puts "7: #{array_includes_array([], [])}" # true

언급URL : https://stackoverflow.com/questions/7387937/how-to-determine-if-one-array-contains-all-elements-of-another-array

반응형