在 C# 中,如果我有一个
List<T>
,并且有一个 T
类型的对象,如何将 List<T>
中的特定项目替换为 T
类型的对象?
这是我尝试过的:
List<CustomListItem> customListItems = new List<CustomListItem>();
CustomListItem customListItem1 = new CustomListItem() { name = "Item 1", date = DateTime.MinValue};
CustomListItem customListItem2 = new CustomListItem() { name = "Item 2", date = DateTime.MinValue };
CustomListItem customListItem3 = new CustomListItem() { name = "Item 3", date = DateTime.MinValue };
customListItems.Add(customListItem1);
customListItems.Add(customListItem2);
customListItems.Add(customListItem3);
CustomListItem newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now };
customListItem2 = customListItems.Where(i=> i.name == "Item 2").First();
customListItem2 = newCustomListItem;
在上面的代码中,我想用
customListItem2
替换 newCustomListItem
。
我是否必须删除列表中的项目,然后插入新项目?我可以不做简单的
customListItem2 = newCustomListItem
作业吗?
用另一个项目替换列表中的项目的最有效方法是什么?
你必须更换的是物品,而不是
customListItem2
的值。只需替换以下内容:
customListItem2 = customListItems.Where(i=> i.name == "Item 2").First();
customListItem2 = newCustomListItem;
有了这个:
customListItem2 = customListItems.Where(i=> i.name == "Item 2").First();
var index = customListItems.IndexOf(customListItem2);
if(index != -1)
customListItems[index] = newCustomListItem;
编辑:
正如 Roman R. 在评论中所述,您可以用简单的
.Where(predicate).First()
替换 First(predicate)
:
customListItem2 = customListItems.First(i=> i.name == "Item 2");
var customListItems = new List<CustomListItem>();
var customListItem1 = new CustomListItem() { name = "Item 1", date = DateTime.MinValue };
var customListItem2 = new CustomListItem() { name = "Item 2", date = DateTime.MinValue };
var customListItem3 = new CustomListItem() { name = "Item 3", date = DateTime.MinValue };
customListItems.Add(customListItem1);
customListItems.Add(customListItem2);
customListItems.Add(customListItem3);
var newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now };
customListItems[customListItems.FindIndex(x => x.name == "Item 2")] = newCustomListItem;
或
public static class ListExtensions
{
public static void Replace<T>(this List<T> list, Predicate<T> oldItemSelector , T newItem)
{
//check for different situations here and throw exception
//if list contains multiple items that match the predicate
//or check for nullability of list and etc ...
var oldItemIndex = list.FindIndex(oldItemSelector);
list[oldItemIndex] = newItem;
}
}
然后
customListItems.Replace(x => x.name == "Item 2", newCustomListItem);
如果列表的顺序对你来说不重要 你可以试试这个
CustomListItem newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now };
customListItem2 = customListItems.Where(i=> i.name == "Item 2").First();
customListItems.Remove(customListItem2);
customListItems.Add(newCustomListItem );
您可以使用选择来构建一个新的 iEnumerable 并替换项目:
customListItems.Select(x => x.name == "Item 2" ? newItem : x).ToList();
我没有测试性能,但我发现这个解决方案非常简洁和明确。
我通常有一些定义关键字段的基本接口,以便我可以更轻松地使用泛型。因此继承 IKey 的类将有一个字符串 Key 字段,它是记录的唯一标识符。
因此,在哈米德的示例之上构建,但具有“添加或替换”概念:
public static void AddOrReplace<T>(this List<T> items, T newItem) where T : class, IKey
{
items.AddOrReplace(x => x.Key == newItem.Key, newItem);
}
public static void AddOrReplace<T>(this List<T> items, Predicate<T> oldItemSelector, T newItem)
{
var index = items.FindIndex(oldItemSelector);
if (index < 0)
{
items.Add(newItem);
}
else
{
items[index] = newItem;
}
}
然后为了实现这些扩展,我可以使用与 list.Add() 类似的语法:
list.AddOrReplace(newItem);
另一种方法是使用
DynamicData
包,列表中还有很多其他设施:
快速解答
确保已安装该软件包:
Install-Package DynamicData -Version 7.4.3
然后
using DynamicData;
DynamicData.ListEx.Replace<CustomListItem>(customListItems, customListItem2, newCustomListItem);
以下是完整的工作解决方案。
工作示例
我的自定义项目类别
public class CustomListItem
{
public string name;
public DateTime date;
public override string ToString()
{
return name + ", " + date.ToString();
}
}
在主要尝试中,请确保在替换之前注释掉分配。
static void Main(string[] args)
{
List<CustomListItem> customListItems = new List<CustomListItem>();
CustomListItem customListItem1 = new CustomListItem() { name = "Item 1", date = DateTime.MinValue };
CustomListItem customListItem2 = new CustomListItem() { name = "Item 2", date = DateTime.MinValue };
CustomListItem customListItem3 = new CustomListItem() { name = "Item 3", date = DateTime.MinValue };
customListItems.Add(customListItem1);
customListItems.Add(customListItem2);
customListItems.Add(customListItem3);
CustomListItem newCustomListItem = new CustomListItem() { name = "Item 4", date = DateTime.Now };
customListItem2 = customListItems.Where(i => i.name == "Item 2").First();
//customListItem2 = newCustomListItem;
DynamicData.ListEx.Replace<CustomListItem>(customListItems, customListItem2, newCustomListItem);
foreach(var customListItem in customListItems)
{
Debug.Print("\n" + customListItem.ToString());
}
}
references: https://github.com/reactivemarbles/DynamicData.
https://dynamic-data.org