Создание списка всех возможных комбинаций

76
5

Я пытаюсь сделать следующее.


Я хочу создать список всех возможных отношений между определенными вещами.


Например. Там Мария, Алиса, июнь, Синди, Элизабет, Бетти, Джакс


Я хотел бы создать все возможные комбинации для списка, подобного этому:


    Мэри, Алиса
    Мэри, июнь
    Мэри Синди
    Мэри, Джакс
    Мэри, Алиса, июнь
    Мэри, Алиса, Синди
    Мария, Алиса, Элизабет
    ...
    Мэри, Алиса, Джакс
    Мария, июнь, Синди
    Мария, июнь, Элизабет
    ...
    Мэри, июнь, Джакс
    Мария, Синди, Элизабет
    Мэри, Синди, Бетти
    Мэри, Синди, Джакс
    ...
    Мэри, Алиса, Июнь, Синди
    Мария, Алиса, июнь, Элизабет
    Мэри, Алиса, июнь, Бетти
    ...
    Мария, Алиса, июнь, Синди, Элизабет
    Мэри, Алиса, июнь, Синди, Бетти

Кто-нибудь знает способ сделать это в SQL, Access или С#? Если там есть другой язык, который я могу использовать в БД, я бы его очень признателен!


Спасибо,
мария

спросил(а) 2021-01-25T15:03:11+03:00 4 месяца, 4 недели назад
1
Решение
88

Для этого вам могут потребоваться рекурсивные запросы, используемые многими современными серверами БД.


ACCESS не является одним из них: (

приведен пример с postres


postgres=# with RECURSIVE y1(b,c,d) as (
postgres(# with x1(a) as (
postgres(# values('a')
postgres(# union all
postgres(# values ('b')
postgres(# union all
postgres(# values ('c')
postgres(# union all
postgres(# values ('d')
postgres(# )
postgres(# select a,a,1
postgres(# from x1
postgres(# union all
postgres(# select a||b,a,d+1
postgres(# from x1
postgres(# join y1 on (a < c)
postgres(# )
postgres-# select *
postgres-# from y1;
b | c | d
------+---+---
a | a | 1
b | b | 1
c | c | 1
d | d | 1
ab | a | 2
ac | a | 2
ad | a | 2
bc | b | 2
bd | b | 2
cd | c | 2
abc | a | 3
abd | a | 3
acd | a | 3
bcd | b | 3
abcd | a | 4
(15 rows)

postgres=#

ответил(а) 2021-01-25T15:03:11+03:00 4 месяца, 4 недели назад
76

SQL может быть очень хорош для такого рода вещей. Он становится липким, если вы хотите идти очень широко, но если бы вы знали, что хотите все комбинации до, скажем, пяти предметов:

DECLARE @things TABLE (n nvarchar(50));

INSERT INTO @things (n) VALUES ('Mary'),('Alice'),('June'),('Cindy'),('Elizabeth'),('Betty'),('Jax'), (null);

SELECT
ISNULL(t1.n + ',', '')
+ ISNULL(t2.n + ',', '')
+ ISNULL(t3.n+ ',', '')
+ ISNULL(t4.n+ ',', '')
+ ISNULL(t5.n, '')
FROM @things AS t1
JOIN @things AS t2 ON 1=1
JOIN @things AS t3 ON 1=1
JOIN @things AS t4 ON 1=1
JOIN @things AS t5 ON 1=1

ответил(а) 2021-01-25T15:03:11+03:00 4 месяца, 4 недели назад
63

Если вы имеете в виду power set, вы можете использовать следующее в С#


public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list)
{
return from m in Enumerable.Range(0, 1 << list.Count)
select
from i in Enumerable.Range(0, list.Count)
where (m & (1 << i)) != 0
select list[i];
}

Использование:


var names = new List<string> { "Mary", "Alice", "June", "Cindy", "Elizabeth", "Betty", "Jax" };
var powerSet = GetPowerSet(names);
foreach (var nameCollection in powerSet)
{
foreach (var name in nameCollection)
{
Console.Write(name);
}
Console.WriteLine();
}

Вы можете удалить любые коллекции с менее чем двумя именами, а также полный набор имен:


var cleaned = powerSet.Where(nc => nc.Count() > 1 && nc.Count() < names.Count());

ответил(а) 2021-01-25T15:03:11+03:00 4 месяца, 4 недели назад
45

Вид неловко, но будет делать трюк или написать SQL-proc с вложенными циклами для каждого имени.


создать отдельную таблицу для каждого имени, например:


CREATE TABLE MARY(name VARCHAR(30));
INSERT INTO MARY VALUES ("Mary");

{do the same for each different name and then}

SELECT *
FROM mary,
alice,
june,
cindy,
elizabeth,
betty,
jax;


Это приведет к созданию декартова произведения без дублирования имен!

ответил(а) 2021-01-25T15:03:11+03:00 4 месяца, 4 недели назад
44

Если у вас есть определенное количество элементов, скажем, Мэри, Алиса, Июнь, Синди, Элизабет, Бетти, Джакс, 8 элементов в этом случае, вы можете вложить 8 циклов, чтобы отображать все возможные перестановки элементов. Если число неизвестно, вам понадобится рекурсивная функция.

ответил(а) 2021-01-25T15:03:11+03:00 4 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема