如果取决于值

时间:2017-11-07 15:56:21

标签: c# arrays linq lambda calculation

我想Lambda我的代码但是卡住了。

基本上: 如果数组对象包含4个具有自己的年份规范和id的成员。然而,该数组可以包含更多具有相同和不同Id和年份的成员(但从不相同的Id和同年)。

会员阵列:

array[0]: Id 1 Year 2010
array[1]: Id 2 Year 2010
array[2]: Id 1 Year 2008
array[3]: Id 1 Year 2009

首先 - 我想删除所有具有2010年特定ID的阵列成员,如果他们在阵列中还有另一年(相同的ID,不同的年份)。所以在这种情况下我想删除[0]但不删除其他成员。

其次 - 我想在2010年之后保持2010年之后的最新一年,即2009年的Id 1,这意味着我也想删除[2]。 (这些年来作为字符串,这就是为什么我将它们转换为int以便在下面的代码中进行比较)

下面是我的代码,其for循环有效,我需要专家Lambda帮助以避免循环:

var x = Member.Length;

for (int i = 0; i < x; i++)
{
    var y = Member[i].id;
    for (int j = i; j < x; j++)
    {
        var z = Member[j].id;
        if (i != j)
        {
            if (y == z)
            {
                if (Member[i].year == "2010") 
                {
                    Member = Member.Where(w => w != Member[i]).ToArray();
                    i--;
                    j--;
                    x--;
                    break;
                }

                var tempI = Convert.ToInt32(Member[i].year);

                var tempJ = Convert.ToInt32(Member[j].year);

                if (tempI > tempJ)
                {
                    Member = Member.Where(w => w != Member[j]).ToArray();
                    i--;
                    j--;
                    x--;
                    break;
                }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

我同意这个要求并没有多大意义,但这就是我解释的方式

var Member = new[]
           {
               new { id = 1, year = "2010" },

               new { id = 2, year = "2010" } ,

               new { id = 1, year = "2008" } ,

               new { id = 1, year = "2009" }  
           };

           var results = from item in Member.Select(x => new { x.id, Year = Convert.ToInt32(x.year), item = x })
                         group item by item.id into sameItems
                         let order = sameItems.OrderByDescending(x => x.Year)
                         let first = order.ElementAtOrDefault(0)
                         let second = order.ElementAtOrDefault(1)
                         select first.Year == 2010 && second != null ? second.item : first.item;

            foreach (var item in results)
            {
                System.Console.WriteLine($"id:{item.id},year:{item.year}");
            }        

答案 1 :(得分:0)

我倾向于避免使用LINQ来更改我正在查询的底层集合。 下面的代码将为每个成员选择最多两个最近的条目。

var result = new List<MemberClass>();
var groups = Member.OrderBy(m => m.Id).ThenByDescending(m => m.Year).GroupBy(m => m.Id).ToList();
groups.ForEach(c => result.AddRange(c.Take(2)));

使用result代替原始数组。

我不知道性能是否是您的考虑因素。随着收藏的增长,上面的代码可能会变慢。

答案 2 :(得分:0)

您的描述和要求不相容,但这是一种解释:

public class Member
{
    public int Id { get; set; }
    public string Year { get; set; }
}

var items = (new List<Member>() {
    new Member() { Id=1, Year="2010" },
    new Member() { Id=2, Year="2010" },
    new Member() { Id=1, Year="2008" },
    new Member() { Id=1, Year="2009" }
}).ToArray();

// Group everythnig by year, then only keep the highest id
var firstFiltered = items
    .GroupBy(
        x => x.Year,
        x => x.Id,
        (year, ids) => new Member()
                        {
                            Id = ids.Last(),
                            Year = year
                        });

var secondFiltered = firstFiltered
    // Only keep years before 2010
    .Where(x => String.Compare(x.Year, "2010") == -1)
    // Then order by Id then Year
    .OrderBy(x => x.Id)
    .ThenBy(x => x.Year)
    // And only keep the last/most recent year
    .GroupBy(
        x => x.Id,
        x => x.Year, 
        (id, years) => new Member() 
                        {
                            Id = id,
                            Year = years.Last()
                        });