2013-02-05 17 views
0

У меня есть переменная List< Tuple< DateTime, double>> myList.
С учетом datetime, надеемся, что он возвращает Tuple, который предшествует datetime с использованием Linq.
Например, if "2013-Feb-08 21:34:00" прилагается, хотите см. Последний Tuple в списке, чье время до этого timestamp.Список Tuple DateTime

Как это сделать с помощью Linq?

Редактировать:
myList.Where (t => t.Item1 < timestamp) .Last();
решил мою проблему. Что лучше с точки зрения производительности по сравнению с
myList.TakeWhile (t => t.Item1 < timestamp) .Last();

+0

использование [.OderByDescending] (http://stackoverflow.com/questions/5344805/linq -orderby-descending-query) – spajce

+0

Элемент, который я хочу, может быть не первым в списке orderby. – Chris

+0

Под «последним», вы имеете в виду элемент с наивысшим индексом в списке или элемент с наивысшим значением «DateTime»? – Guffa

ответ

2

С MoreLinq MaxBy (доступный от NuGet):

myList.Where(t => t.Item1 < timestamp).MaxBy(t => t.Item1); 

Или (если элементы отсортированы):

myList.TakeWhile(t => t.Item1 < timestamp).Last(); 

UPDATE (с двоичным поиском) написать компаратор:

public class MyComparer : IComparer<Tuple<DateTime, double>> 
{ 
    public int Compare(Tuple<DateTime, double> x, Tuple<DateTime, double> y) 
    { 
     return x.Item1.CompareTo(y.Item1); 
    } 
} 

Затем поиск

int index = myList.BinarySearch(new Tuple<DateTime, double>(timestamp, 0), 
            new MyComparer()); 

    if (index == 0) 
     // there is no items before timestamp 

    if (index > 0) 
     result = myList[index - 1]; // your item is previous 

    if (index < 0) // no tuple with date equal to timestamp 
     var nearestIndex = ~index; 
     if (nearestIndex > 0) 
      result = myList[nearestIndex - 1]; 
+0

@AlvinWong вы не можете использовать двоичный поиск с последовательностью 'IEnumerable' (которая также не сортируется). Он перечисляет все элементы, но не использует внутреннее хранилище для их хранения. Он просто берет один макс. Элемент. –

+0

О, кажется, что мой мозг путается комментариями, предлагающими использовать 'SortedDictionary'. Кажется, что ОП должен действительно использовать его и написать свой собственный алгоритм бинарного поиска. –

+0

@lazyberezovsky Ошибка компиляции: MaxBy не определен в System.Collections.Generic.IEnumerable << System.Tuple >>. Любая идея, что не так? – Chris

0

myList.Where (t => t.Item1 < datetime) .OrderByDescending (t => t.Item1) .Last();

1
var result = myList.OrderByDescending(t => t.Item1) 
    .SkipWhile(t => t.Item1 > timestamp) 
    .First(); 
1

Чтобы получить максимальную производительность, вы не должны использовать LINQ вообще. Двоичный поиск дает производительность O (log n) на основе O (n), которую может предложить LINQ.

Создать компаратор для вашего типа:

public class MyListComparer : IComparer<Tuple<DateTime, double>> { 

    public int Compare(Tuple<DateTime, double> x, Tuple<DateTime, double> y) { 
    return x.Item1.CompareTo(y.Item1); 
    } 

} 

Используйте компаратор с BinarySearch method:

int idx = myList.BinarySearch(new Tuple<DateTime, double>(new DateTime(2013,2,8,21,34,0), 0), new MyListComparer()); 
if (idx < 0) { 
    idx = (~idx) - 1; 
} 
Tuple<DateTime, double> item = myList[idx]; 
+0

И какая разница? –

+0

@lazyberezovsky: Разница в том, что O (log n) меньше O (n), что обеспечивает лучшую производительность. – Guffa

+0

Я спросил о различии между моими и вашими ответами :) MyListComparer vs MyComparer –

Смежные вопросы