2012-02-03 81 views
2

我正在嘗試執行以下操作。創建所有可能組合的列表

我想創建一個特定事物之間所有可能關係的列表。

例如。還有瑪麗·愛麗絲,月,辛迪·克勞,伊麗莎白,貝蒂,賈克斯

我想對於像這樣的列表創建所有可能的組合:

  • 瑪麗愛麗絲
  • 瑪麗,六月
  • 瑪麗·辛迪
  • 瑪麗,賈克斯
  • 瑪麗·愛麗絲,六月
  • 瑪麗·愛麗絲,辛迪
  • 瑪麗·愛麗絲,伊麗莎白 ...
  • 瑪麗·愛麗絲,賈克斯
  • 瑪麗,月,辛迪
  • 瑪麗,六月,伊麗莎白 ...
  • 瑪麗,六月,賈克斯
  • 瑪麗辛迪,伊麗莎白
  • 瑪麗,辛迪,貝蒂
  • 瑪麗,辛迪,賈克斯 ...
  • 瑪麗·愛麗絲,月,辛迪
  • 瑪麗·愛麗絲,六月,伊麗莎白
  • 瑪麗·愛麗絲,六月,貝蒂 ...
  • 瑪麗·愛麗絲,月,辛迪·克勞,伊麗莎白
  • 瑪麗·愛麗絲,月,辛迪,貝蒂

任何人都知道在SQL,Access或C#中執行此操作的方法嗎?如果有另一種語言可以在數據庫上使用,我會非常感激!

感謝, 瑪麗亞

+2

所有可能的組合,直到什麼?二十一行?瑪麗,瑪麗是否有效?爲什麼沒有瑪麗,伊麗莎白? – Oded 2012-02-03 19:57:51

+0

爲什麼沒有'瑪麗'(只有1個名字)?瑪麗,愛麗絲和愛麗絲,瑪麗一樣嗎? – 2012-02-03 20:31:34

+1

@Oded - Mary,Mary在這種情況下無效。瑪麗,伊麗莎白將是有效的,我只是跳到了兩對組合中的最後一個組合到瑪麗,傑克斯。 – Maria 2012-02-03 21:06:38

回答

0

如果你有一個定義的元素,數說,瑪麗·愛麗絲,月,辛迪·克勞,伊麗莎白,貝蒂,賈克斯,在這種情況下8個元素,你可以窩8個循環顯示元素的每種可能的排列。如果該數字未知,則需要遞歸函數。

+0

感謝whitelionV我會進一步研究遞歸函數。 – Maria 2012-02-03 21:08:19

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雖然對於像瑪麗,瑪麗,瑪麗,瑪麗,瑪麗這樣的東西,當它應該是瑪麗時,你確實有一些清理工作。另外,你應該嘗試在'FROM'子句中多次列出'@ things'而不用'JOIN'條件。 – Yuck 2012-02-03 20:13:07

+0

@Yuck是正確的清理。我只是想幫瑪麗亞開始。她可能也想擺脫一些晃來晃去的逗號。 FROM子句中的多個項目大部分時間都會工作,但這是一種令我感到困惑的樣式。 – Andrew 2012-02-03 20:27:36

+0

你有什麼是'FROM @things AS t1 CROSS JOIN @things AS t2 CROSS JOIN ...' – 2012-02-03 20:47:23

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 2012-02-03 21:10:19

+0

沒有,這應該是好的,你需要.NET框架3.5或以上,你應該添加一個使用System.Linq;語句放在源代碼的頂部,並確保您引用了System.Core程序集。 – devdigital 2012-02-03 21:15:39

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 2012-02-03 21:08:53

0

類尷尬的樣本,但會做的伎倆,或寫爲每名嵌套循環的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; 

這將生成一個笛卡兒積,不會重複任何名字!