2012-02-03 2 views
2

Я пытаюсь сделать следующее.Создание списка всех возможных комбинаций

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

Например. Там Мэри Элис, июнь, Синди, Элизабет, Бетти, Jax

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

  • Мэри Элис
  • Мэри, июнь
  • Мэри Синди
  • Мэри, Jax
  • Мэри Элис, июнь
  • Мэри Элис, Синди
  • Мэри Элис, Элизабет ...
  • Мэри Элис, Jax
  • Мэри, июнь, Синди
  • Мэри, июнь, Элизабет ...
  • Мэри, июнь, Jax
  • Mary Синди, Элизабет
  • Мэри, Синди, Бетти
  • Мэри, Синди, Jax ...
  • Мэри Элис, июнь, Синди
  • Мэри Элис, июнь, Элизабет
  • Мэри Элис, июнь, Бетти ...
  • Мэри Элис, июнь, Синди, Элизабет
  • Мэри Элис, июнь, Синди, Бетти

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

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

+2

Все возможные комбинации до чего? Двадцать строк? Действительно ли «Мария, Мэри»? Почему нет «Мэри, Элизабет»? – Oded

+0

Почему нет 'Mary' (всего 1 имя)? «Мария, Алиса» такая же, как «Алиса, Мэри»? –

+1

@Oded - Мэри, Мэри не будет действительна в этом случае. Мэри, Элизабет была бы верна, я просто перешел к последней комбинации в этой 2-парной комбинации с Мэри, Джакс. – Maria

ответ

0

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

+0

Спасибо whitelionV Затем я буду исследовать рекурсивные функции. – Maria

2

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 
+1

+1 Хотя у вас есть какая-то очистка для вещей, которые выглядят как «Мария, Мэри, Мэри, Мэри, Мэри», когда это должно быть просто «Мария». Также вы должны попробовать просто перечислять '@ things' несколько раз в разделе' FROM' без условия 'JOIN'. – Yuck

+0

@ Yuck прав насчет очистки. Я просто пытаюсь помочь Марии начать. Она может также хотеть избавиться от некоторых болтающихся запятых. Множество элементов в предложении FROM будет работать большую часть времени, но это стиль, который я считаю запутанным. – Andrew

+0

У вас есть 'FROM @things AS t1 CROSS JOIN @things AS t2 CROSS JOIN ...' –

1

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

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(); 
} 

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

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

Хмм, попробовав это прямо сейчас, посмотрим, смогу ли я заставить его работать. Спасибо devdigital. также, я использую VS 2008 любую разницу в коде для выше с этим? – Maria

+0

Нет, это должно быть хорошо, вам нужна .NET framework 3.5 или выше, и вы должны добавить использование System.Linq; в верхней части источника и убедитесь, что вы ссылаетесь на сборку System.Core. – devdigital

3

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

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=# 
+0

Спасибо Алессандро, я не знаком с postgres, но я рассмотрю это решение дальше. – Maria

0

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

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

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; 

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