Scala генерирует уникальные пары из списка
вход :
val list = List(1, 2, 3, 4)
желаемый результат :
Iterator((1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4))
этот код работает :
for (cur1 <- 0 until list.size; cur2 <- (cur1 + 1) until list.size)
yield (list(cur1), list(cur2))
но это не кажется оптимальным, есть ли лучший способ сделать это ?
2 ответов
здесь .combinations
способ встроенным:
scala> List(1,2,3,4).combinations(2).toList
res0: List[List[Int]] = List(List(1, 2), List(1, 3), List(1, 4), List(2, 3), List(2, 4), List(3, 4))
возвращает Iterator
, но я добавил .toList
как раз для печатать результат. Если вы хотите, чтобы ваши результаты в форме кортежа, вы можете сделать:
scala> List(1,2,3,4).combinations(2).map{ case Seq(x, y) => (x, y) }.toList
res1: List[(Int, Int)] = List((1,2), (1,3), (1,4), (2,3), (2,4), (3,4))
вы также упомянули уникальность, поэтому вы можете применить .distinct
для вашего входного списка уникальность не является предварительным условием вашей функции, потому что .combination
не будет дедуплицировать для вас.
.комбинации-это правильный способ генерации уникальных произвольных групп любого размера, другое альтернативное решение, которое не проверяет уникальность в первую очередь, использует foldLeft таким образом:
val list = (1 to 10).toList
val header :: tail = list
tail.foldLeft((header, tail, List.empty[(Int, Int)])) {
case ((header, tail, res), elem) =>
(elem, tail.drop(1), res ++ tail.map(x => (header, x)))
}._3
будет:
res0: List[(Int, Int)] = List((1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (2,3), (2,4), (2,5), (2,6), (2,7), (2,8), (2,9), (2,10), (3,4), (3,5), (3,6), (3,7), (3,8), (3,9), (3,10), (4,5), (4,6), (4,7), (4,8), (4,9), (4,10), (5,6), (5,7), (5,8), (5,9), (5,10), (6,7), (6,8), (6,9), (6,10), (7,8), (7,9), (7,10), (8,9), (8,10), (9,10))
Если вы ожидаете, что будут дубликаты, вы можете превратить выходной список в набор и вернуть его в список, но тогда вы потеряете заказ. Таким образом, не рекомендуется, если вы хотите иметь уникальность, но должны быть предпочтительно, если вы хотите создать все пары, включенные равные элементы.
например. Я использовал его в области машинного обучения для генерации всех продуктов между каждой парой переменных в пространстве объектов, и если две или более переменных имеют одинаковое значение, я все равно хочу создать новую переменную, соответствующую их продукту, даже если эти недавно созданные "переменные взаимодействия" будут иметь дубликаты.