2011-03-01 162 views
3
var listOne = new string[] { "dog", "cat", "car", "apple"}; 
var listTwo = new string[] { "car", "apple"}; 

我需要的是按listTwo中的項目順序排列listOne(如果存在)。所以新的列表將按照這個順序; 「汽車」,「蘋果」,「狗」,「貓」從另一個數組順序排序一個數組?

我想在LINQ中做到這一點,

var newList = from l1 in listOne 
       join l2 in listTwo on l1 equals l2 in temp 
       from nl temp.DefaultIfEmpty() 
       select nl; 

但是它返回null顯然我的Linq-Fu很弱。任何意見表示讚賞。

+1

「listOne」中是否存在重複?如果是這樣,他們應該保存嗎? – 2011-03-01 18:35:03

回答

4

您需要列表1中的所有項目,然後是listOne中的其餘項目?

var results = listTwo.Intersect(listOne).Union(listOne); 
foreach (string r in results) 
{ 
    Console.WriteLine(r); 
} 
+1

爲什麼你需要第二個Except?這是一個聯盟;他們不會出現兩次。 – 2011-03-01 18:33:16

+0

你從哪裏得知它是一個工會? – 2011-03-01 18:36:31

+0

我已經改變了Concat一分鐘,但你是對的。沒有這個例外的聯盟可能更優雅。 listTwo.Intersect(那麼listOne).Union(那麼listOne); – 2011-03-01 18:38:41

3

嗯,讓我重組你的排序要求:

  1. 首先,所有的從第一個列表中的項目,這也是目前在第二個列表,並返回它們的順序它們出現在該名單,:第二個列表中的所有元素(如果它們出現在第一個列表中)
  2. 然後,第一個列表中不在第二個列表中的所有項目,然後按它們出現的順序返回那第一個名單

該代碼會做的伎倆:

void Main() 
{ 
    var listOne = new string[] { "dog", "cat", "car", "apple"}; 
    var listTwo = new string[] { "car", "apple"}; 

    var elements1 = 
     from element in listTwo 
     where listOne.Contains(element) 
     select element; 
    var elements2 = 
     from element in listOne 
     where !listTwo.Contains(element) 
     select element; 

    elements1.Concat(elements2).Dump(); 
} 

你也可以把它改寫沒有LINQ語法使它有點短:

void Main() 
{ 
    var listOne = new string[] { "dog", "cat", "car", "apple"}; 
    var listTwo = new string[] { "car", "apple"}; 

    var elements = listTwo.Where(e => listOne.Contains(e)) 
     .Concat(listOne.Where(e => !listTwo.Contains(e))); 

    elements.Dump(); 
} 

輸出(通過LINQPad):

car 
apple 
dog 
cat 
+0

好的解決方案,具有listOne {「A」,「A」,「B」,「C」}和listTwo {「A」,「C」} IMO的BTW應該產生「{」A「,」A 「,」C「,」B「}'不是'{」A「,」C「,」B「},就像你的代碼一樣......不知道OP是否需要這樣做) – digEmAll 2011-03-01 18:39:38

+0

順便說一句'Intersect'和'Except'比'Where''Contains'更有效率 – 2011-03-01 18:42:06