现在我来了一个阶段,将我的所有数据作为缓存(对象)中的列表,我接下来要做的就是从列表中删除一些实例。
通常,我会像这样删除:
List<T> list;
List<T2> toBeRemovedItems;
// populate two lists
foreach(T2 item in toBeRemovedItems)
{
list.Remove(delegate(T one) {
// build a condition based on item
// return true or false
});
}
更具体地说,我实际上构建或填充了动态类(不是正式定义的类)的BeRemvoedItems列表。例如,T类类似于MyClass,删除代码是:
class MyClass<C> {
public string Value1 { get; set; }
public int Value2 { get; set; }
public C ObjectC { get; set; }
}
....
List<MyClass<C>> list;
// populate list
// populate toBeRemovedItems. Here is an example of hard-coded codes:
var toBeRemovedLItems = new[] {
new { Value1="a", Value2 = 1},
new { Value2="x", Value2 = 10},
...
};
// toBeRemovedItems may be the result of Select from a collection
foreach(var item in toBeRemovedLItems)
{
list.Remove(delegate(MyClass one) {
return one.Value1 = item.Value1 && one.Value2 < item.Value2;
});
}
我尝试在MSDN中的Remove()
界面中搜索IEnumerable
方法,但我找不到Remove()
的方法(IEnumerable
只使用了Remove(...)
列举)。在List类中,有几个重载的IEnumerable
方法。我不确定是否有其他方法可以使用LINQ或Lambda表达式从列表中删除项目?
顺便说一句,我想到了一种方法来对列表进行查询,以获得具有Where条件的子集或新{{1}}列表,类似于从列表中移动项目。但是,我更喜欢从缓存列表中删除项目,在某些情况下,我无法将类中的列表属性重置为新列表(例如私有集)。
答案 0 :(得分:41)
您可以使用 RemoveAll :
方法MyClass one; //initialize MyClass
list.RemoveAll(item => one.Value1 == item.Value1 && one.Value2 < item.Value2);
答案 1 :(得分:21)
您可以使用LINQ的Where方法过滤掉不应该是列表一部分的值。结果是IEnumerable<T>
删除了元素。
var res = list.Where(item => !(one.Value1 == item.Value1 && one.Value2 < item.Value2));
这不会更新原始List<T>
实例,而是会创建一个删除了值的新IEnumerable<T>
。
答案 2 :(得分:5)
如果我正确地得到了问题,要从两个List中生成一个唯一的集合。
为此,您可以使用以下
列表list1; 清单list2;
列表list3 = list1.Except(list2)
list3将包含唯一的项目。
答案 3 :(得分:4)
我同意Jared关于过滤掉某些项目的建议,但join
Value1
似乎是一种更有效的方法:
var res = from item1 in list
join item2 in toBeRemovedList
on item1.Value1 equals item2.Value1
where item1.Value2 >= item2.Value2
select item1;
更新:显然我在阅读理解上失败了 - 新方法:
var removeDict = toBeRemovedList.ToDictionary(i => i.Value1, i => i.Value2);
list.RemoveAll(item => {
int itemToRemoveValue2;
if(removeDict.TryGetValue(item.Value1, out itemToRemoveValue2))
return item.Value2 < itemToRemoveValue2;
return false;
});
当然,如果要删除的列表可以以字典开头,那就更好了。最终,我们只是想让Value1
的匹配更有效率。
答案 4 :(得分:2)
foreach(var item in toBeRemovedLItems) {
list.RemoveAll(one => one.Value1 == item.Value1 && one.Value2 < item.Value2);
}
再次太迟了。哦,好吧。
答案 5 :(得分:1)
对于非列表的集合(无法公开RemoveAll
),您仍然可以删除带有单行的项目。
要替换内联,只需生成要删除的项目列表,然后运行它并执行删除代码。
var dictionary = new Dictionary<string, string>(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}};
dictionary
.Where(where_item =>
((where_item.Key == "foo") && (where_item.Value == "0"))
|| ((where_item.Key == "boo") && (where_item.Value == "1"))
)
.ToList()
.ForEach(remove_item => {
dictionary.Remove(remove_item.Key);
});
要替换副本,只需生成已过滤的可枚举项并返回新副本。
var dictionary0 = new Dictionary<string, string>(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}};
var dictionary1 = dictionary0
.Where(where_item =>
((where_item.Key == "foo") && (where_item.Value == "0"))
|| ((where_item.Key == "boo") && (where_item.Value == "1"))
)
.ToDictionary(each_item => each_item.Key, each_item => each_item.Value);
答案 6 :(得分:0)
也许你正试图做这样的事情?
List<T> firstList;
List<T2> toBeRemovedItems;
List<T> finalList;
foreach(T item in firstList)
{
toBeRemovedItems = CheckIfWeRemoveThisOne(item.Number, item.Id);
if (toBeRemovedItems == null && toBeRemovedItems.Count() == 0)
finalList.Add(item);
}
这就是我设法解决一个问题,即摆脱List<ViewModel>
和List<Model>
之间的重复问题。我使用CheckIfWeRemoveThisOne
函数来检查item.Number
是否属于某个其他项目,使用ID作为定义特征。如果它找到另一个项目(重复),而不是尝试将其从原始列表中删除(我正在返回List<Model>
并且首先在我的函数中获得List<ViewModel>
,所以无论如何,我对如何做到这一点表示怀疑),我刚刚建立了一个新列表 - 如果发现它没有问题,将结果添加到其中。