【问题标题】:How to query a List<MyClass> with another list<int> into a new List<MyClass>如何查询一个 List<MyClass> 和另一个 list<int> 到一个新的 List<MyClass>
【发布时间】:2017-10-02 07:27:45
【问题描述】:

我有两个列表:

static List<Parts> partList = new List<Parts>();

它所指的类:

class Parts
{
    int chassisNumber;

    public int ChassisNumber
    {
        get { return chassisNumber; }
        set { chassisNumber = value; }
    }

    int partsCount;

    public int PartsCount
    {
        get { return partsCount; }
        set { partsCount = value; }
    }

还有一个:

static List<int> shuffledChassisList = new List<int>();

shuffledChassisList 包含加载到 List ChassisNumber 中的机箱编号子集。 我想使用 shuffledChassisList 将 List 查询成一个新的 List,例如:List filteredPartList。

我尝试使用 Linq,但未能编写一个有效的解决方案来创建一个包含过滤结果的新列表。

然后,我想使用此过滤列表根据零件编号将零件分类到新列表中(例如:我想将 List filteredPartList 中的所有零件复制到 List emptyPackageList 中,其中零件的 partsCount 为 0)。

到目前为止,我得到了这个,但不确定在 foreach 循环中要写什么:

static List<Parts> emptyPackageList = new List<Parts>();

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0);

foreach (var part in emptyPackage)
{
    emptyPackageList.Add(new Parts(??));
}

如果可以编写一种方法来完成这两件事,那对我来说很好。

编辑: 我需要两个列表的原因是因为我查询数据库以获取底盘编号和属于它的零件数量。我询问了社区,但不幸的是,似乎无法在选定的底盘号上运行此查询。所以我有所有底盘编号 (List&lt;Parts&gt; partList) 的零件计数,我需要用我正在寻找的那些 (List&lt;int&gt; shuffledChassisList) 进行过滤,然后按零件计数分组到新列表中。

如果可以或更容易通过List&lt;int&gt; shuffledChassisList 过滤List&lt;Parts&gt; partList,然后按partsCount 对结果进行分组,然后将Parts 复制到几个新列表中,那么这也是一个可以接受的解决方案。

【问题讨论】:

  • 不清楚这两个列表的部分是如何连接到给定代码sn -p的
  • shuffledChassisList 包含 chassisNumbers(但仅是 partList 中的子集),它在 Parts 类中也可用。查看我对布鲁诺回答的评论,了解为什么需要有两个不同的列表。谢谢。
  • 你应该澄清它而不是 cmets - 对未来的读者来说很清楚

标签: c# linq


【解决方案1】:

您的类没有指定构造函数,因此只有默认构造函数。要使用数据填充新实例,请使用对象初始化器语法:

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0);
foreach (var part in emptyPackage)
{
    emptyPackageList.Add(new Parts { ChassisNumber = part.ChassisNumber, PartsCount = part.PartsCount } );
}

另外,如果已经使用 linq,则使用 .Select 投射新实例:

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0)
                                   .Select(p => new Parts {
                                       ChassisNumber = part.ChassisNumber, 
                                       PartsCount = part.PartsCount 
                                   }).ToList();

请注意,当您实例化新对象并设置其属性时,这会创建对象的深层副本。如果浅拷贝就足够了,那么只需:

var emptyPackage = filteredPartList.Where(p => p.partsCount == 0).ToList();

另外考虑以下几点:

  1. 由于您的属性实现是默认实现,请使用自动属性:

    class Parts
    {
        public int ChassisNumber { get; set; }
        public int PartsCount { get; set; }
    } 
    
  2. 实现一个拷贝构造函数或者IClonable接口然后:

    //copy constructor
    filteredPartList.Where(p => p.partsCount == 0).Select(p => new Parts(p));
    //clone
    filteredPartList.Where(p => p.partsCount == 0).Select(p => p.Clone());
    

如果我正确理解了您的更新,那么:

var result = filteredPartList.Where(p => p.partsCount == 0 && 
                                         shuffledChassisList.Contains(p.ChassisNumber))
                             .GroupBy(p => partsCount)
                             .ToList();

还可以考虑将shuffledChassisList 更改为HashSet&lt;int&gt;,因此Contains 将是O(1) 操作而不是O(n)

【讨论】:

  • 谢谢,我会在家里试试这个,让你知道我有什么。
【解决方案2】:

也许我没有得到你的正确意图,但这是你可以做的:

如果您有零件列表并希望按 PartsCount 对它们进行分类:

var categorized = myList.GroupBy(p=>p.PartsCount, p=>p);

如果您想从一个列表中获取所有项目(如果 id 属于另一个):

var filtered = myList.Where(p=>idList.Contains(p.Id));

也许通过结合这两种方法你可以得到你想要的(这对我来说还是有点不清楚)

【讨论】:

  • 我查询了一个数据库以获取底盘编号和属于它的零件数量。我询问了社区,但不幸的是,似乎无法在选定的底盘号上运行此查询。所以我有所有底盘编号的零件计数,我需要用我正在寻找的那些进行过滤,然后按零件计数分组到新列表中。这就是我写的原因,在方法中处理过滤器和分组会很好。如何从您的第二个代码创建一个新列表,将 ToList() 附加到末尾?
  • 是的,只需添加 .ToList() 将其转换为列表
  • 谢谢,我会在家里试试这个,让你知道我有什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-24
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
相关资源
最近更新 更多