在.NET中合并两个列表并保留单一属性。

huangapple go评论68阅读模式
英文:

Join two lists in .NET while maintaining single property

问题

在.NET中,我有两个相同的列表,每个项的结构如下:

public class InputRecord
{
    public string Product { get; set; }
    public int OriginYear { get; set; }
    public int DevelopmentYear { get; set; }
    public decimal IncValue { get; set; }
}

我尝试使用LINQ来连接这两个记录列表,并在其他属性都匹配的情况下更新IncValue。我的代码如下:

var output = template.Join(records,
    t => new { t.Product, t.OriginYear, t.DevelopmentYear },
    r => new { r.Product, r.OriginYear, r.DevelopmentYear },
    (t, r) => { t.IncValue = r.IncValue; return t; }).ToList();

template 包含大约50个记录,而 records 包含12个条目。我期望输出会有50个记录,其中 IncValue 在其他属性匹配的情况下被更新,但实际输出只有12个记录。我做错了什么?

英文:

I have two identical lists in .NET, this is how single item looks like:

public class InputRecord
{
    public string Product { get; set; }
    public int OriginYear { get; set; }
    public int DevelopmentYear { get; set; }
    public decimal IncValue { get; set; }
}

I'm trying to join two lists of these records using LINQ while updating IncValue where all other properties matches. My code looks like that:

var output = template.Join(records,
    t => new { t.Product, t.OriginYear, t.DevelopmentYear },
    r => new { r.Product, r.OriginYear, r.DevelopmentYear },
    (t, r) => { t.IncValue = r.IncValue; return t; }).ToList();

Template contains about 50 records, while records contains 12 entries. I expect the output to have 50 records with IncValue updated where all other properties matched, however my output is only 12 records. What I'm doing wrong?

答案1

得分: 1

不要使用"join",因为它只返回在两个输入序列中都有匹配键的匹配项,你可以尝试在两个集合之间使用"group join" 操作。

var output = template
    .GroupJoin(
        records,
        t => new { t.Product, t.OriginYear, t.DevelopmentYear },
        r => new { r.Product, r.OriginYear, r.DevelopmentYear },
        (t, rs) => { 
            var record = rs.FirstOrDefault(); 
            if (record != null) { 
                t.IncValue = record.IncValue; 
            }
            return t; 
        })
    .ToList();

GroupJoin 方法通过将左侧列表(template)的元素与右侧列表(records)中匹配的元素进行分组来执行左外连接。

我在.NET Fiddle中使用了以下两个集合进行了测试:

// 定义模板和记录集合
var template = new List<Item>()
{
    new Item() { Product = "A", OriginYear = 2018, DevelopmentYear = 1, IncValue = 100 },
    new Item() { Product = "A", OriginYear = 2018, DevelopmentYear = 2, IncValue = 200 },
    new Item() { Product = "B", OriginYear = 2019, DevelopmentYear = 1, IncValue = 300 },
    new Item() { Product = "B", OriginYear = 2019, DevelopmentYear = 2, IncValue = 400 }
};
var records = new List<Item>()
{
    new Item() { Product = "A", OriginYear = 2018, DevelopmentYear = 2, IncValue = 250 },
    new Item() { Product = "B", OriginYear = 2019, DevelopmentYear = 1, IncValue = 350 },
    new Item() { Product = "C", OriginYear = 2020, DevelopmentYear = 1, IncValue = 500 }
};

输出的项目是:

Product: A, OriginYear: 2018, DevelopmentYear: 1, IncValue: 100
Product: A, OriginYear: 2018, DevelopmentYear: 2, IncValue: 250
Product: B, OriginYear: 2019, DevelopmentYear: 1, IncValue: 350
Product: B, OriginYear: 2019, DevelopmentYear: 2, IncValue: 400

如果这不是你需要的结果,我建议分享一些示例数据。

英文:

Instead of using "join" which will only return matching items that have matching keys in both input sequences, can you try using the "group join" operation between two collections instead

var output = template
    .GroupJoin(
        records,
        t =&gt; new { t.Product, t.OriginYear, t.DevelopmentYear },
        r =&gt; new { r.Product, r.OriginYear, r.DevelopmentYear },
        (t, rs) =&gt; { 
            var record = rs.FirstOrDefault(); 
            if (record != null) { 
                t.IncValue = record.IncValue; 
            }
            return t; 
        })
    .ToList();

The GroupJoin method performs a left outer join by grouping the elements from the left list (template) with the matching elements from the right list (records).

I played around in .NET Fiddle using the following 2 collections

    // Define the template and records collections
    var template = new List&lt;Item&gt;()
    {
        new Item() { Product = &quot;A&quot;, OriginYear = 2018, DevelopmentYear = 1, IncValue = 100 },
        new Item() { Product = &quot;A&quot;, OriginYear = 2018, DevelopmentYear = 2, IncValue = 200 },
        new Item() { Product = &quot;B&quot;, OriginYear = 2019, DevelopmentYear = 1, IncValue = 300 },
        new Item() { Product = &quot;B&quot;, OriginYear = 2019, DevelopmentYear = 2, IncValue = 400 }
    };
    var records = new List&lt;Item&gt;()
    {
        new Item() { Product = &quot;A&quot;, OriginYear = 2018, DevelopmentYear = 2, IncValue = 250 },
        new Item() { Product = &quot;B&quot;, OriginYear = 2019, DevelopmentYear = 1, IncValue = 350 },
        new Item() { Product = &quot;C&quot;, OriginYear = 2020, DevelopmentYear = 1, IncValue = 500 }
    };

The items in the output was

Product: A, OriginYear: 2018, DevelopmentYear: 1, IncValue: 100
Product: A, OriginYear: 2018, DevelopmentYear: 2, IncValue: 250
Product: B, OriginYear: 2019, DevelopmentYear: 1, IncValue: 350
Product: B, OriginYear: 2019, DevelopmentYear: 2, IncValue: 400

If this is not what you needed then I would probably suggest sharing some sample data.

huangapple
  • 本文由 发表于 2023年3月7日 05:19:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655952.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定