У меня есть список вроде
var myList = new List<object> {
new { Day = "Sunday", ID = 15 },
new { Day = "Monday", ID = 20 },
new { Day = "Tuesday", ID = 80 }
};
теперь я хотел бы получить предыдущий день данного ID. например, 80 понедельника и воскресенья должны быть результатом для 20. Список упорядочен по ID!
У меня есть простой способ определить дневную стоимость? идеальным было бы решение linq.
var result = myList.LastOrDefault(item => item.ID < 80);
Быстрый n грязный способ:
myList.Where(c => c.ID < currentId).OrderByDescending(c => c.ID)
.Select(c => c.Day).FirstOrDefault();
myList.TakeWhile(o => o.ID <= givenID).Select(o => o.Day).LastOrDefault();
Это предполагает, что myList упорядочен. В противном случае вы можете просто OrderBy()
Не используйте var
и object
. Попробуй это:
private class ItemList
{
/// <summary>
/// Day
/// </summary>
public string Day { get; set; }
/// <summary>
/// ID
/// </summary>
public int ID { get; set; }
}
А также:
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());
}
}
(Основано на вычислении разницы с предыдущим элементом с LINQ)
для чистого пути linq, чтобы найти предыдущее значение
var value = myList.SelectWithPrevious((prev, cur) => new { prev = prev, cur= cur}).Where((w) => w.cur.ID == 80).First();
Console.WriteLine(value.prev.Day);
расширение
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;
}
}
}
Это дает больше, чем вам нужно. Но это может помочь в будущем.
var item = myList.Single(l => l.ID == 80);
var i = myList.IndexOf(item);
var j = (i - 1) % myList.Count;
var prevItem = myList[j];
Это получит элемент, который вы ищете, найдите его в списке, вычтите его (по модулю вы можете обернуть конец списка), а затем получите предыдущий элемент из списка по индексу.
Изменение: использование индекса, а не нечто вроде FindLast, позволяет вам не нуждаться в значениях идентификатора, которые должны быть в порядке возрастания с днями. например, понедельник может составлять 100 и вторник 15, и это не изменит ситуацию.