这部分Linq过滤器的代码审查

时间:2018-08-23 08:49:41

标签: c# linq optimization

我是C#的新手,我想知道是否可以删除每个C并使用Linq进行一次操作。我想返回一个已经过滤的IEnumerable。是否有可能做到这一点?每个建议都是值得欢迎的,非常感谢

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Linq
{
class Oggetto
{
    public int Id { get; set; }
    public string MyProperty { get; set; }
    public int Deleted { get; set; }
}
    class Program
{
    static void Main(string[] args)
    {
        IEnumerable<Oggetto> lista = new List<Oggetto> {
            new Oggetto(){ Id = 1, MyProperty = "Propr1", Deleted = 0 },
            new Oggetto(){ Id = 1, MyProperty = "Propr2", Deleted = 1 },
            new Oggetto(){ Id = 2, MyProperty = "Prop3", Deleted = 0 },
            new Oggetto(){ Id = 3, MyProperty = "Propr4", Deleted = 0 },
            new Oggetto(){ Id = 3, MyProperty = "Prop5", Deleted = 1 }
        };


        foreach (var item in lista.Where(x => x.Deleted == 1).GroupBy(x => x.Id).Select(g => g.First()))
        {
            item.MyProperty = string.Join(",", lista.Where(t => t.Id == item.Id).Select(x => x.MyProperty).ToArray());
            Console.WriteLine(item.Id);
            Console.WriteLine(item.MyProperty);
        }

        Console.ReadLine();
    }
}

}

3 个答案:

答案 0 :(得分:1)

您可以为此使用projection

        var orderedList = lista.GroupBy(x => x.Id)
                               .Where(x => x.Any(y => y.Deleted == 1))
                               .Select(x => new Oggetto
                                            {
                                                Id = x.Key, MyProperty = string.Join(",", x.Select(v => v.MyProperty))
                                            });

        foreach (var item in orderedList)
        {
            Console.WriteLine(item.Id);
            Console.WriteLine(item.MyProperty);
        }

无论如何,正如@Alex所说的,您应该将Deleted字段类型替换为bool,就像@Marco Salerno所说的那样,用英语开始编程时,您不会后悔。

答案 1 :(得分:1)

首先用意大利语进行 STOP 编程,然后开始用英语进行编程。

无论如何,这应该是更好的方法:

class Program
{
    static void Main(string[] args)
    {
        List<Item> items = new List<Item> {
            new Item{ Id = 1, MyProperty = "Propr1", Deleted = 0 },
            new Item{ Id = 1, MyProperty = "Propr2", Deleted = 1 },
            new Item{ Id = 2, MyProperty = "Prop3", Deleted = 0 },
            new Item{ Id = 3, MyProperty = "Propr4", Deleted = 0 },
            new Item{ Id = 3, MyProperty = "Prop5", Deleted = 1}
        };

        foreach (IGrouping<int,Item> group in items.GroupBy(x => x.Id).ToList())
        {
            List<Item> groupItems = group.ToList();
            Item deletedItem = groupItems.Where(x => x.Deleted == 1).FirstOrDefault();
            if(deletedItem != null)
            {
                deletedItem.MyProperty = string.Join(",", groupItems.Select(x => x.MyProperty).ToArray());
                Console.WriteLine(deletedItem.Id);
                Console.WriteLine(deletedItem.MyProperty);
            }
        }
    }
}

class Item
{
    public int Id { get; set; }
    public string MyProperty { get; set; }
    public int Deleted { get; set; }
}

答案 2 :(得分:1)

首先,我将避免使用groupBy语句。这是很多不必要的开销。您可以改用distinct。这将为您提供所有您需要知道的ID。

var ids = lista.Where(x => x.Deleted).Select(x => x.Id).Distinct();

然后,您可以选择所需的所有元素:

var items = ids.Select(i => lista.Where(x => x.Id == i));

,结果为List of Lists。为了易于使用,我将其转换为Dictionary<K, V>(在这种情况下,最后一步是Dictionary<long, List<string>>

var dictionary = items.ToDictionary(l => l.First().Id, l => l.Select(o => o.MyProperty).ToList());

您现在获得了一个“很好且经过过滤”的收藏集,您可以使用任何喜欢的方式(或仅输出它)

foreach (var item in dictionary)
{
     Console.WriteLine($"Id: {item.Key}");
     Console.WriteLine($"Properties: {string.Join(", ", item.Value)}");
}

我也将您的课程做了一些更改:

class Oggetto
{
    public int Id { get; set; }
    public string MyProperty { get; set; }
    // bool instead of int - Deleted has only 2 states
    public bool Deleted { get; set; }
}