假设我有LINQ查询,比如:
var authors = from x in authorsList
where x.firstname =="Bob"
select x;
鉴于 authorsList的类型为 List
或者,换句话说,如何删除 authorsList 中的所有内容?
authorsList = authorsList.Where(x => x.FirstName!="Bob").ToList();
但是,这将只更改 authorsList的值,而不是从先前的集合中删除authors。 或者,你可以使用 RemoveAll
:
authorsList.RemoveAll(x => x.FirstName =="Bob");
如果你确实需要根据其他集合进行操作,则可以使用HashSet,RemoveAll和Contains:
var setToRemove = new HashSet<Author>(authors);
authorsList.RemoveAll(x => setToRemove.Contains(x));
var authorsList = new List<Author>()
{
new Author{ Firstname ="Bob", Lastname ="Smith" },
new Author{ Firstname ="Fred", Lastname ="Jones" },
new Author{ Firstname ="Brian", Lastname ="Brains" },
new Author{ Firstname ="Billy", Lastname ="TheKid" }
};
var authors = authorsList.Where(a => a.Firstname =="Bob");
authorsList = authorsList.Except(authors).ToList();
authorsList = authorsList.Except(authorsList.Where(a=>a.Firstname=="Billy")).ToList();
你不能使用标准的LINQ运算符来执行这里操作,因为LINQ提供查询,而不是更新。
但是你可以生成一个新的List 并替换旧的。
var authorsList = GetAuthorList();
authorsList = authorsList.Where(a => a.FirstName!="Bob").ToList();
或者你可以在第二个传递中删除 authors
中的所有项目。
var authorsList = GetAuthorList();
var authors = authorsList.Where(a => a.FirstName =="Bob").ToList();
foreach (var author in authors)
{
authorList.Remove(author);
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace ListRemoveTest
{
class Program
{
private static Random random = new Random( (int)DateTime.Now.Ticks );
static void Main( string[] args )
{
Console.WriteLine("Be patient, generating data..." );
List<string> list = new List<string>();
List<string> toRemove = new List<string>();
for( int x=0; x <1000000; x++ )
{
string randString = RandomString( random.Next( 100 ) );
list.Add( randString );
if( random.Next( 1000 ) == 0 )
toRemove.Insert( 0, randString );
}
List<string> l1 = new List<string>( list );
List<string> l2 = new List<string>( list );
List<string> l3 = new List<string>( list );
List<string> l4 = new List<string>( list );
Console.WriteLine("Be patient, testing..." );
Stopwatch sw1 = Stopwatch.StartNew();
l1.RemoveAll( toRemove.Contains );
sw1.Stop();
Stopwatch sw2 = Stopwatch.StartNew();
l2.RemoveAll( new HashSet<string>( toRemove ).Contains );
sw2.Stop();
Stopwatch sw3 = Stopwatch.StartNew();
l3 = l3.Except( toRemove ).ToList();
sw3.Stop();
Stopwatch sw4 = Stopwatch.StartNew();
l4 = l4.Except( new HashSet<string>( toRemove ) ).ToList();
sw3.Stop();
Console.WriteLine("L1.Len = {0}, Time taken: {1}ms", l1.Count, sw1.Elapsed.TotalMilliseconds );
Console.WriteLine("L2.Len = {0}, Time taken: {1}ms", l1.Count, sw2.Elapsed.TotalMilliseconds );
Console.WriteLine("L3.Len = {0}, Time taken: {1}ms", l1.Count, sw3.Elapsed.TotalMilliseconds );
Console.WriteLine("L4.Len = {0}, Time taken: {1}ms", l1.Count, sw3.Elapsed.TotalMilliseconds );
Console.ReadKey();
}
private static string RandomString( int size )
{
StringBuilder builder = new StringBuilder();
char ch;
for( int i = 0; i <size; i++ )
{
ch = Convert.ToChar( Convert.ToInt32( Math.Floor( 26 * random.NextDouble() + 65 ) ) );
builder.Append( ch );
}
return builder.ToString();
}
}
}
结果如下:
Be patient, generating data...
Be patient, testing...
L1.Len = 985263, Time taken: 13411.8648ms
L2.Len = 985263, Time taken: 76.4042ms
L3.Len = 985263, Time taken: 340.6933ms
L4.Len = 985263, Time taken: 340.6933ms
我们可以看到,在这种情况下,最好的选择是使用 RemoveAll( HashSet )