Как найти случайный индекс в массиве A, значение которого не появляется в массиве B?

Допустим, массив A содержит это:

[0, 1, 8, 3, 10, 6, 2]

И массив B содержит это:

[1, 2]

Как я могу генерировать случайный индекс в массиве A, значение которого не появляется в массиве B? Возможные индексы в приведенном выше примере:

0, 2, 3, 4, 5

Но как это сделать в Swift?

3 ответа

Решение

Когда вы хотите работать с элементами массива и их индексами, enumerated() может быть хорошим инструментом:

var a = [0, 1, 8, 3, 10, 6, 2]
var b = [1, 2]
var possibleIndices = a.enumerated()
    .filter{!b.contains($0.element)}
    .map{$0.offset}
print(possibleIndices)
//->[0, 2, 3, 4, 5]

(Когда b может быть большим, лучше сделать это Set.)

А потом:

(Когда мы можем предположить, b никогда не содержит все содержимое a.)

var randomIndexToPossibleIndices = Int(arc4random_uniform(UInt32(possibleIndices.count)))
var randomIndex = possibleIndices[randomIndexToPossibleIndices]

Если вышеуказанное предположение не может быть выполнено, possibleIndices может быть пустым. Так что тебе лучше сделать randomIndex Необязательный:

var randomIndex: Int? = nil
if !possibleIndices.isEmpty {
    var randomIndexToPossibleIndices = Int(arc4random_uniform(UInt32(possibleIndices.count)))
    randomIndex = possibleIndices[randomIndexToPossibleIndices]
}

Спасибо за Мартина Р.

Как насчет работы с сетами?

let a = [0, 1, 8, 3, 10, 6, 2]
let b = [1, 2]

var setA = Set(a)
var setB = Set(b)

setA.subtract(setB)

var index: Int? = nil
if let first = setA.first {
    index = a.index(of: first)
}
// if index == nil no such index exists

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

Тогда все, что вам нужно сделать, это найти случайный индекс, который вы хотите использовать, и получить доступ к указанному элементу:

#if os(Linux)
    let j = Int(random() % ((count-1)))
#else
    let j = Int(Int(arc4random()) % ((count-1)))
#endif

Даст вам правильный индекс

Если вы затем используете этот индекс и элемент для поиска оригинального элемента в вашем массиве, вы получите свой результат.

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

Посмотрите на функциональное программирование коллекций в swift здесь: Swift Руководство по уменьшению фильтра карт

Например, вы можете использовать фильтр следующим образом (и я не знаю, является ли это лучшим способом):

collection.filter {
  var found = false;
  for element in bCollection {
      if element == $0 {
          found = true;
      }
  }
  return !found; // Might be better to turn true/false thing around in the above code to slightly improve performance.
}
Другие вопросы по тегам