2013-06-11 2 views
2

в LINQ, можно объединить множество списков (одного и того же типа), таким образом, что два списка,Объединение списков в LINQ

список 1 = {а, Ь, с} и список 2 = {х, у, г}

превращается в {[1, а], [1, б], [1, с], [2, х], [2, у], [2, г]}

где [] представляет пару, содержащую «идентификатор списка»

Проблема заключается в наличии колод произвольных карт, где каждая колода представляет собой список в коллекции списков.

Я пытаюсь создать запрос, чтобы я мог выбирать только карты в определенной колоде или карты, похожие на 2 или более колоды.

Это, вероятно, повторяющийся вопрос, но я не знаю, как искать вопрос дальше, чем у меня уже есть.

+0

http://stackoverflow.com/questions/11051299/linq-merge-lists –

+0

, что означает ли это '{[1, a], [1, b], [1, c], [2, x], [2, y], [2, z]}'? –

+0

@jayram у нас есть список, связанный автоматически, не спам-ссылки. если вы считаете, что это на самом деле обман, отметьте его как таковой (или скажите так, если у вас недостаточно репутации для этого) – Blorgbeard

ответ

1

Вы можете объединить списки, как:

var first = new List<string> {"a","b","c"}; 
var second = new List<string> {"x","y","z"}; 

var merged = first.Select(item => new { ListIndex = 1, Value = item}).ToList(); 
merged.AddRange(second.Select(item => new { ListIndex = 2, Value = item}); 

//or use concat 
var merged = first.Select(item => new { ListIndex = 1, Value = item}); 
    .Concat(second.Select(item => new { ListIndex = 2, Value = item}); 

В качестве альтернативы, если у вас есть источники в чем-то вроде :

List<List<string>> lists = new List<List<string>> 
          { 
           new List<string> {"a","b","c"}, 
           new List<string> {"x","y","z"} 
          }; 

вы можете сделать:

var merged = lists.SelectMany((item, index) => 
         item.Select(s => new { ListIndex = index, Value = s})); 

Обратите внимание, что это приведет к созданию списка на основе 0, поэтому, если вам действительно нужен список из 1 базы, просто сделайте ListIndex = index +1.

Кроме того, если вы будете использовать это много, я бы создал его в качестве конкретного объекта, что-то вроде

struct ListIdentValue 
{ 
    public int ListIndex {get; private set;} 
    public string Value {get; private set;} 

    public ListIdentValue(int listIndex, string value) {...} 
} 
+0

принял этот ответ в качестве ответа, поскольку он содержал большую часть информации, в действительности многие из этих ответов будут работать по разным причинам, и мне было трудно выбрать, какие из них принять. –

3
List<List<int>> lists; 

var combined = lists.Select((l, idx) => new { List = l, Idx = idx }) 
    .SelectMany(p => p.List.Select(i => Tuple.Create(p.Idx + 1, i))); 
3
var list1 = new List<string>() {a,b,c}; 
var list2 = new List<string>() {x,y,z}; 

var combined = list1.Select(x => new { id = 1, v = x }).Concat(list2.Select(x => new { id = 2, v = x })); 
0
string[] a = { "a", "b", "c" }; 
    string[] b = { "x", "z", "y" }; 


    var t = 
    (
    from ai in a 
    select new { listNo = 1, Item = ai } 
    ).Union 
    (
    from bi in b 
    select new { listNo = 2, Item = bi } 
     ); 

или

var t = 
     (
     from ai in a 
     select new object[] { 1, ai } 
     ).Union 
     (
     from bi in b 
     select new object[] { 2, bi } 
      ); 
1

Попробуйте использовать Concat

new[] {'a','b','c'} 
.Select(v=>new Tuple<int,char>(1, v)) 
.Concat(
    new[] {'x','y','z'}.Select(v=>new Tuple<int,char>(2, v)) 
) 
+0

Не общепринятая практика использования 'Tuple.Create', а не конструктора в общем классе? –

+0

В чем проблема с использованием конструктора здесь, @BobVale? См. Http://msdn.microsoft.com/en-us/library/dd387181.aspx, что эквивалентно. – Sklivvz

+1

'new Tuple' заставляет вас быть явным о типах,' Tuple.Create' может их вывести, поэтому оба варианта имеют сценарии использования, где один более подходит, чем другой. – SWeko

2

Обычно я предлагаю Enumerable.Zip для объединения нескольких списков, но вы, кажется, на самом деле хотите, чтобы сцепить несколько списков с lis t счетчик.

public IEnumerable<Tuple<int,T>> Combine<T>(params IEnumerable<T>[] lists) { 
    return lists.Select((x,i) => x.Select(y => Tuple.Create(i+1,y))).SelectMany (l =>l); 
} 

UPDATE полностью пропустил, что SelectMany имеет параметр индекса, поэтому приведенный выше код может быть записан как

public IEnumerable<Tuple<int,T>> Combine<T>(params IEnumerable<T>[] lists) { 
    return lists.SelectMany((x,i) => x.Select(y => Tuple.Create(i+1,y))); 
} 

Затем вы можете сделать

var list1 = new List<string> { "a", "b", "c" }; 
var list2 = new List<string> { "x", "y", "z" }; 
var combined = Combine(list1,list2); 

Совмещенный будет перечислимый из кортежей, с Item1, являющимся lis t индекс (начиная с 1) и Item2 является значением.

Этот метод будет обрабатывать несколько списков, чтобы вы могли так же легко назвать его:

var list3 = new List<string> { "f", "g" }; 
var combined = Combine(list1,list2,list3); 
Смежные вопросы