Подтвердить что ты не робот

Как вы проверяете, содержит ли значения массива одно или несколько значений?

Я ищу, чтобы увидеть, имеет ли массив одно или несколько значений внутри него. Например, что-то вроде этого:

[1,2,3,4,5,6].include?([4,1])  # => true
[4,1,6,2].include?([4,1])  # => true
[3,4,7].include?([4,1])  # => false

Конечно, "включить?" метод может проверять только одно значение. Есть ли способ проверки нескольких значений?

4b9b3361

Ответ 1

EDIT: Я поддерживаю альтернативное решение Mark Thomas, в котором используется ядро ​​ Set class.

В то время как мое решение более строго отвечает на вопрос о том, как это сделать с массивами, sjsc может извлечь пользу из рассмотрения его собственного случая и изучения возможности использования наборов вместо этого.

Существует много действительных reasond для использования массивов (поддерживая порядок, позволяющий дублировать), для которых все еще достаточно, но если ни один из них не задействован, sjsc может действительно выиграть от использования Set вместо Array, и к этому степень, решение Mark семантически превосходит.


Я не знаю ни одного метода библиотеки, который делает это, но было бы не слишком сложно написать свою собственную функцию.

class Array
  def subset?(a)
    (self - a).length == 0
  end
end

Я уверен, что есть более эффективные способы, чтобы сделать это, но это должно делать то, что вы ищете.

Выполнение работы с пересечением массивов и в основном составляет одно и то же.

class Array
  def subset?(a)
    (self & a).length == length
  end
end

Оптимизация на этом уровне не слишком сильно поможет, но то, что вы не хотите делать, - это несколько раз собрать массивы:

class Array
  # don't do this
  def subset?(a)
    (self & a) == a
  end
end

Ответ 2

>> [1,2,3,4,5,6] & [4,1]
=> [1, 4]
>> [1,2,3,4,5,6] & [7,9]
=> []
>>

Ответ 3

Это заданная операция. Set находится в стандартной библиотеке.

require 'set'

a = Set[1,2,3,4,5,6]
b = Set[4,1]

b.subset? a
#=> true

Ответ 4

Быстрое и грязное расширение подхода @Schwartzie:

larger_array = [1,2,3,4,5,6]
smaller_array = [4,1]
smaller_array.all? {|smaller_array_item| larger_array.include?(smaller_array_item)}

Ответ 5

База на курму и предложение spyle, вот мой тест:

([1,2,3,4,5,6] и [4,1]). any? # = > true

Однако .any? превратит любые объекты в true

([1,2,3,4,5,6] и [6,7]). # = > true

Итак, я думаю, что здесь может быть рабочий:

([1,2,3,4,5,6] и [6,7]). length == [6,7].length # = > false

(large_array и small_array).length == small_array.length

Ответ 6

Что случилось с [1,2,3,4,5,6].include?(4) and [1,2,3,4,5,6].include?(1)?

Ответ 7

Мой вывод заключается в том, что метод Subtraction обычно хорош, но фактические объекты Установить быстро растут, так как они четко оптимизированы для этого типа вычислений.

Используя этот script: https://gist.github.com/1996001

Я получил эти контрольные результаты (на Ruby 1.9.2p290):

SUBTRACTION
- subset
  0.180000   0.000000   0.180000 (  0.189767)
- partial subset
  0.170000   0.000000   0.170000 (  0.178700)
- non subset
  0.180000   0.000000   0.180000 (  0.177606)

INTERSECTION
- subset
  0.190000   0.000000   0.190000 (  0.194149)
- partial subset
  0.190000   0.000000   0.190000 (  0.191253)
- non subset
  0.190000   0.000000   0.190000 (  0.195798)

SET
- subset
  0.050000   0.000000   0.050000 (  0.048634)
- partial subset
  0.040000   0.000000   0.040000 (  0.045927)
- non subset
  0.050000   0.010000   0.060000 (  0.052925)

Что я считаю довольно поразительным, особенно если вы посмотрите источник:

# File 'lib/set.rb', line 204

def subset?(set)
  set.is_a?(Set) or raise ArgumentError, "value must be a set"
  return false if set.size < size
  all? { |o| set.include?(o) }
end

через: http://rubydoc.info/stdlib/set/1.9.2/Set#subset%3F-instance_method

Ответ 8

Мне нравится куруми ответ, но просто чтобы выбросить еще один:

>> set1 = [1,2,3,4,5,6]
[
    [0] 1,
    [1] 2,
    [2] 3,
    [3] 4,
    [4] 5,
    [5] 6
]
>> set2 = [4,1]
[
    [0] 4,
    [1] 1
]
>> set1.any?{ |num| set2.include?(num) }
true
>> set2 = [8,9]
[
    [0] 8,
    [1] 9
]
>> set1.any?{ |num| set2.include?(num) }
false

Ответ 9

@kurumi имеет это право, но я думал, что добавлю, что иногда использую это небольшое расширение, когда мне нужно только подмножество массива (обычно хеш-ключи):

class Hash
  # Usage { :a => 1, :b => 2, :c => 3}.except(:a) -> { :b => 2, :c => 3}
  def except(*keys)
    self.reject { |k,v|
      keys.include? k
    }
  end

  # Usage { :a => 1, :b => 2, :c => 3}.only(:a) -> {:a => 1}
  def only(*keys)
    self.dup.reject { |k,v|
      !keys.include? k
    }
  end
end

class Array
  def except(*values)
    self.reject { |v|
      values.include? v
    }
  end

  def only(*values)
    self.reject { |v|
      !values.include? v
    }
  end
end

Ответ 10

Простой и лучший способ:

([4,1] - [1,2,3,4,5,6]) пустым? # = > true

([4,1] - [4,1,6,2]) пустым? # = > true

([4,1] - [3,4,7]) пустым? # = > false

Ответ 11

Это проверит, существует ли элемент в массиве:

students = ["jim", "bob", "sally"]
teachers = ["mrs. jones", "mrs. sharpe", "mrs. ray"]

puts "what your name ?"
answer = gets.chomp

if answer.include?(students.to_s)
  puts "you are a student"

elsif
  puts "you are a teacher"

end