2

i have a list like

var myList = new List<object> { 
    new { Day = "Sunday", ID = 15 },
    new { Day = "Monday", ID = 20 }, 
    new { Day = "Tuesday", ID = 80 } 
};

now i would like to get the previous day of a given ID. e.g. 80 leads to Monday and Sunday should be the result for 20. The List is ordered by ID!

Ist there a easy way to determine the day-value? ideal would be a linq solution.

fubo
  • 44,811
  • 17
  • 103
  • 137
  • 7
    How about using a [LinkedList](https://msdn.microsoft.com/en-us/library/he2s3bh7(v=vs.110).aspx). – Sam Axe Apr 01 '15 at 09:46

6 Answers6

7
var result = myList.LastOrDefault(item => item.ID < 80);
stefankmitph
  • 3,236
  • 2
  • 18
  • 22
3

A quick n dirty way:

myList.Where(c => c.ID < currentId).OrderByDescending(c => c.ID)
     .Select(c => c.Day).FirstOrDefault();
Stefan
  • 17,448
  • 11
  • 60
  • 79
1
var item = myList.Single(l => l.ID == 80);
var i = myList.IndexOf(item);
var j = (i - 1) % myList.Count;

var prevItem = myList[j];

This will get the item that you're searching for, find it's index in the list, subtract one (the modulo allows you to wrap around the end of the list) and then get the previous item from the list by index.

Edit: The use of the index rather than something like FindLast allows you to not need the ID values to be in ascending order with the days. e.g. Monday could be 100 and Tuesday 15 and it wouldn't make a difference.

brimble2010
  • 17,796
  • 7
  • 28
  • 45
1
myList.TakeWhile(o => o.ID <= givenID).Select(o => o.Day).LastOrDefault();

This is assuming myList is ordered. Otherwise you can just throw in an OrderBy()

Dennis_E
  • 8,751
  • 23
  • 29
1

(Based on Calculate difference from previous item with LINQ)

for a pure linq way to find the prev value

var value = myList.SelectWithPrevious((prev, cur) => new { prev = prev, cur= cur}).Where((w) => w.cur.ID == 80).First();
            Console.WriteLine(value.prev.Day);

Extension

public static IEnumerable<TResult> SelectWithPrevious<TSource, TResult> (this IEnumerable<TSource> source,Func<TSource, TSource, TResult> projection)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        TSource previous = iterator.Current;
        while (iterator.MoveNext())
        {
            yield return projection(previous, iterator.Current);
            previous = iterator.Current;
        }
    }
}

This does give more than you needed. But, it may help in future.

Community
  • 1
  • 1
Steve Drake
  • 1,968
  • 2
  • 19
  • 41
0

Do not use var and object. Try this:

private class ItemList
{

    /// <summary>
    /// Day
    /// </summary>
    public string Day { get; set; }

    /// <summary>
    /// ID
    /// </summary>
    public int ID { get; set; }

}

And:

List<ItemList> myList = new List<ItemList> { 
    new ItemList() { Day="S", ID=10 },
    new ItemList() { Day="M", ID=20 },
    new ItemList() { Day="T", ID=30 },
};

foreach(ItemList key in myList)
{
    ItemList result = myList.FindLast(x=>x.ID<key.ID);
    if(result!=null)
    {
        MessageBox.Show("Prev ID: " + result.ID.ToString());
    }
}
GRUNGER
  • 486
  • 3
  • 14