2009-04-07 2 views
3

я получил list<list<string>>Любой шанс получить уникальные записи с помощью Linq (C#)?

в list[x][0] являются записями, из которых я хочу, чтобы выбрать уникальные записи, таким образом, такая запись не будет в любом другом list[x][0], когда я выбираю его, я хотел бы целый ряд list[x] быть выбрана , Я не нашел подходящий exapmple для этого в Linq, пожалуйста, помогите :(

EDIT

Когда Джон Скит просит меня уточнить, я не могу отрицать ;-)

list<list<string>> 

содержит список таблицы строк. Каждая строка «table» содержит несколько ключей list[x][several_items], и я хочу получить уникальные записи из списка -> значение FIRST в этой «таблице».

Таким образом:

item[0] = "2","3","1","3" 
item[1] = "2","3","4","2" 
item[3] = "10","2" 
item[4]= "1","2" 

-> уникальный будет означать, что я могу получить на строки item[3] and item[4], как уникальный. потому что первое появление числа/строки важно.

Если есть 2 или больше записей/строк (item[x] of which first item (item[x][0]) существует более чем один раз в списке, это не единственный.

Первый элемент каждого списка имеет важное значение для определения уникальности. Может быть, было бы проще, если бы кто-то может помочь найти способ найти неповторимый -> поэтому из приведенного выше примера в список я бы получил только элемент [0] и пункт [1]

+0

list [x] [0] определенно одна строка - как эта карта соответствует «записям»? Я неясно ... –

ответ

10

EDIT: Я обновил реализацию UniqueBy внизу чтобы быть значительно более эффективными и только один раз переходить через источник.

Если я понял вас правильно LY (вопрос довольно неясно - это действительно поможет, если вы могли бы привести пример) это то, что вы хотите:

public static IEnumerable<T> OnlyUnique<T>(this IEnumerable<T> source) 
{ 
    // No error checking :) 

    HashSet<T> toReturn = new HashSet<T>(); 
    HashSet<T> seen = new HashSet<T>(); 

    foreach (T element in source) 
    { 
     if (seen.Add(element)) 
     { 
      toReturn.Add(element); 
     } 
     else 
     { 
      toReturn.Remove(element); 
     } 
    } 
    // yield to get deferred execution 
    foreach (T element in toReturn) 
    { 
     yield return element; 
    } 
} 

EDIT: Хорошо, если вы только заботиться о первом элементе списка уникальности, мы должны изменить его несколько:

public static IEnumerable<TElement> UniqueBy<TElement, TKey> 
    (this IEnumerable<TElement> source, 
    Func<TElement, TKey> keySelector) 
{ 
    var results = new LinkedList<TElement>(); 
    // If we've seen a key 0 times, it won't be in here. 
    // If we've seen it once, it will be in as a node. 
    // If we've seen it more than once, it will be in as null. 
    var nodeMap = new Dictionary<TKey, LinkedListNode<TElement>>(); 

    foreach (TElement element in source) 
    { 
     TKey key = keySelector(element); 
     LinkedListNode<TElement> currentNode; 

     if (nodeMap.TryGetValue(key, out currentNode)) 
     { 
      // Seen it before. Remove if non-null 
      if (currentNode != null) 
      { 
       results.Remove(currentNode); 
       nodeMap[key] = null; 
      } 
      // Otherwise no action needed 
     } 
     else 
     { 
      LinkedListNode<TElement> node = results.AddLast(element); 
      nodeMap[key] = node; 
     } 
    } 
    foreach (TElement element in results) 
    { 
     yield return element; 
    } 
} 

Вы назвали бы его:

list.UniqueBy(row => row[0]) 
+0

да, я хочу только тех, которые встречаются только один раз – Skuta

+0

Я повторно изложил свой вопрос с дополнительной информацией – Skuta

+0

Хмм. Боюсь, я все еще не понимаю. Вас интересует только первый элемент каждого списка? Редактирование, чтобы попробовать это ... –

2

Что-то вроде этого, возможно?

теперь я абсолютно уверен, что это будет работать для вас, учитывая ваше разъяснение :)

var mylist = new List<List<string>>() { 
    new List<string>() { "a", "b", "c" }, 
    new List<string>() { "a", "d", "f" }, 
    new List<string>() { "d", "asd" }, 
    new List<string>() { "e", "asdf", "fgg" } 
}; 
var unique = mylist.Where(t => mylist.Count(s => s[0] == t[0]) == 1); 

unique теперь содержит «д» и «е» записи из выше.

+0

Я думаю, что у вас есть. Я проверю! :) – Skuta

+0

есть ли шанс забронировать? так что я ищу a, записи? : D – Skuta

+0

Наверное .. Вы можете объяснить это немного больше? :) – Blorgbeard

0

Вы можете сохранить список и индекс/dictionary:

List<List<string>> values; 
Dictionary<string, List<string>> index; 

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

values[x].Add(newString); 
index[newString] = values[x]; 

Тогда вы можете получить правильный список по:

List<string> list = index[searchFor] 

Вы потерять некоторые (минимальную) производительность и память при построении индекса, но вы получаете много при извлечении данных.

Если строка не уникальна, вы также можете сохранить Список> в индексе dictionary /, чтобы разрешить несколько результатов на индексный ключ.

Извините, нет Linq, это не выглядит так круто, но у вас есть быстрый поиск, и IMHO код поиска более ясен.

+0

Не могли бы вы рассказать мне больше об этом подходе? это выглядит круто. – Skuta

0

Я просто продолжу и добавлю это в бой.

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication1 { 
    class Program { 
     static void Main(string[] args) { 
      List<string> xx = new List<string>() { "xx", "yy", "zz" }; 
      List<string> yy = new List<string>() { "11", "22", "33" }; 
      List<string> zz = new List<string>() { "aa", "bb", "cc" }; 
      List<List<string>> x = new List<List<string>>() { xx, yy, zz, xx, yy, zz, xx, yy }; 
      foreach(List<string> list in x.Distinct()) { 
       foreach(string s in list) { 
        Console.WriteLine(s); 
       } 
      } 
     } 
    } 
} 
+0

Согласно моим знаниям о linq (почти ничего на самом деле), это неправильно. пожалуйста, проверьте мой пост еще раз :( – Skuta

+0

Ну, с новой информацией в вашем сообщении, мне кажется, что вы используете неправильную структуру для хранения своих данных. Возможно, вам будет лучше с хеш-таблицей или datatable. – Ariel

+0

на самом деле, теперь, когда я читайте больше только прямо вверх массив. – Ariel

1

Вот некоторые Linq для вас.

List<List<string>> Records = GetRecords(); 
// 
List<List<string> UniqueRecords = Records 
    .GroupBy(r => r[0]) 
    .Where(g => !g.Skip(1).Any()) 
    .Select(g => g.Single()) 
    .ToList(); 
2

Вот код, в котором вы нуждаетесь. Он отлично работает для меня, чтобы выбрать ТОЛЬКО различные значения.

//distinct select in LINQ to SQL with Northwind 
var myquery = from user in northwindDC.Employees 
       where user.FirstName != null || user.FirstName != "" 
       orderby user.FirstName 
       group user by user.FirstName into FN 
       select FN.First(); 
Смежные вопросы