简体   繁体   English

替换列表的值<Class>

[英]Replace values of List<Class>

I have two List<class> , List1 and List2 which contains multiple columns: RowNo , Value1 , Value2 , etc. as follows 我有两个List<class>List1List2 ,其中包含多个列: RowNoValue1Value2等,如下所示

List1 清单1

| RowNo | Value |
|-------|-------|
| 1     | 11    |
| 2     | 22    |
| 3     | 33    |
| 4     | 88    |

List2 清单2

| RowNo | Value |
|-------|-------|
| 1     | 44    |
| 2     | 55    |
| 3     | 66    |

I want to replace the value of element of List1 with the value of element of List2 if the RowNo matches.The output I want to generate is as follows 如果RowNo匹配,我想用List2的元素值替换List1的元素值。我要生成的输出如下

Desired result 所需结果

| RowNo | Value |
|-------|-------|
| 1     | 44    |
| 2     | 55    |
| 3     | 66    |
| 4     | 88    |

Any Ideas or suggestions? 有任何想法或建议吗? How can I achieve this? 我该如何实现? What can be the best and efficient way to do this? 最佳和有效的方法是什么?

You can just use a loop to compare the values in List1 with List2 , and if a match is found, update the Value 您可以使用循环将List1的值与List2进行比较,如果找到匹配项,则更新Value

foreach (var item in List1)
{
    var match = List2.FirstOrDefault(x => x.RowNo == item.RowNo);
    if (match != null)
    {
        item.Value = match.Value;
    }
}

Using Linq 使用Linq

List1.ForEach(l1 => l1.Value = (List2.FirstOrDefault(l2 => l2.RowNo == l1.RowNo) ?? l1).Value);

The Value property of l1 list element will be set to itself if no element will be found on the List2 list. 如果在List2列表上找不到元素,则l1列表元素的Value属性将设置为自身。

Full code 完整代码

class MyClass
{
    public int RowNo { get; set; }
    public int Value { get; set; }
}

var List1 = new List<MyClass>()
{
    new MyClass(){RowNo = 1, Value = 11},
    new MyClass(){RowNo = 2, Value = 22},
    new MyClass(){RowNo = 3, Value = 33},
    new MyClass(){RowNo = 4, Value = 88},
};

var List2 = new List<MyClass>()
{
    new MyClass(){RowNo = 1, Value = 44},
    new MyClass(){RowNo = 2, Value = 55},
    new MyClass(){RowNo = 3, Value = 66}
};

List1.ForEach(l1 => l1.Value = (List2.FirstOrDefault(l2 => l2.RowNo == l1.RowNo) ?? l1).Value);
  List1.ForEach(x =>
        {
            var item = List2.FirstOrDefault(y => y.RowNo == x.RowNo);
            if (item != null)
            {
                x.Value = item.Value;
            }
        });
  1. Put all data of list1 into a Dictionary (key is the RowNo). list1所有数据放入Dictionary (键为RowNo)。

  2. Loop over list2 to update the Dictionary. 循环遍历list2以更新字典。

  3. Convert the data of the Dictionary to a List . Dictionary的数据转换为List

It approaches an O(n) operation. 它接近O(n)运算。

Use this extension method to achieve what you want: 使用此扩展方法可以实现您想要的:

public static class LinqExtentions
{
    public static void Project<T>(this IEnumerable<T> lst1, IEnumerable<T> lst2,
        Func<T, object> key, Action<T, T> action)
    {
        foreach (var item1 in lst1)
        {
            var item2 = lst2.FirstOrDefault(x => key(x).Equals(key(item1)));
            if (item2 != null)
            {
                action(item1, item2);
            }
        }
    }
}

then you can use it like this: 那么您可以像这样使用它:

List1.Project(List2, x => x.RowNo, (y, z) => { y.Value = z.Value; });

What it does 它能做什么

is projecting one list over the other, then matching the key values in both ( RowNo in your example), when two items have the same key then the action supplied in the third parameter is applied, in this example, you want elements in the first list to have the same Value as elements in the second list, that's exactly what this delegate does: 将一个列表投影到另一个列表上,然后匹配两个列表中的键值(在您的示例中为RowNo ),当两个项目具有相同的键时,则应用第三个参数中提供的操作,在此示例中,您希望第一个元素中的元素列表具有与第二个列表中的元素相同的Value ,这正是此委托所做的:

(y, z) => { y.Value = z.Value; }

you can use this extension method to achieve the same requirement for any pair of lists: 您可以使用此扩展方法来实现任何一对列表的相同要求:

  1. Call Project on the list you want to change. 在要更改的列表上调用Project
  2. Pass the the list of the values you want to assign to the first list, as the first parameter. 将要分配的值列表传递给第一个列表,作为第一个参数。
  3. Pass the key property as the second parameter. 传递key属性作为第二个参数。
  4. The third parameter is the action you want to apply on your list. 第三个参数是您要在列表上应用的操作。

You can loop over List1 and check if List2 contains a match then fill the result in a new list 您可以遍历List1并检查List2包含匹配项,然后将结果填充到新列表中

List<YourClass> result = new List<YourClass>();
for (int i = 0; i < List1.Count; i++)
{
    YourClass resRowValue = List1[i];
    if (List2.Count > i && List2[i].RowValue.equals(resStrRowValue.RowValue)
        resStr.RowValue = List2[i].RowValue;

    result.Add(resRowValue);
}
//set the result to List1
List1 = result;

You can do this also using linq 您也可以使用linq执行此操作

List1 = List1.Select(x => {
    int i = List1.IndexOf(x);

    YourClass newValue = List2.FirstOrDefault(y => y.RowValue.Equals(x.RowValue));
    if (newValue != null)
        x.RowValue = newValue.RowValue;

    return x;
}).ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM