C# LINQ在简单操作中的效率
我最近发现了LINQ,我发现它的使用非常有趣。目前,我有以下功能,我不确定它是否会更有效,毕竟,产生相同的输出 你能告诉我你对此的看法吗 该函数以非常简单的方式删除标点符号:C# LINQ在简单操作中的效率,c#,performance,linq,C#,Performance,Linq,我最近发现了LINQ,我发现它的使用非常有趣。目前,我有以下功能,我不确定它是否会更有效,毕竟,产生相同的输出 你能告诉我你对此的看法吗 该函数以非常简单的方式删除标点符号: private static byte[] FilterText(byte[] arr) { List<byte> filteredBytes = new List<byte>(); int j = 0; //index for filteredArray
private static byte[] FilterText(byte[] arr)
{
List<byte> filteredBytes = new List<byte>();
int j = 0; //index for filteredArray
for (int i = 0; i < arr.Length; i++)
{
if ((arr[i] >= 65 && arr[i] <= 90) || (arr[i] >= 97 && arr[i] <= 122) || arr[i] == 10 || arr[i] == 13 || arr[i] == 32)
{
filteredBytes.Insert(j, arr[i]) ;
j++;
}
}
//return the filtered content of the buffer
return filteredBytes.ToArray();
}
专用静态字节[]过滤器文本(字节[]arr)
{
List filteredBytes=新列表();
int j=0;//filteredArray的索引
对于(int i=0;i 如果((arr[i]>=65&&arr[i]=97&&arr[i]=65&&a=97&&aLINQ通常比简单循环和过程代码的效率稍低,但差别通常很小,而且简洁易读通常值得将简单的投影和过滤转换为LINQ
如果性能真的很重要,请测量它,然后自己决定LINQ代码的性能是否足够。LINQ非常适合保持简单。从性能角度看,如果您开始对列表、数组等进行大量转换,它确实会成为一个问题
MyObject.where(...).ToList().something().ToList().somethingelse.ToList();
众所周知,这是一个杀手,请尽可能晚地转换为最终列表。螺钉性能,LINQ是令人惊讶的,因为:
private static bool IsAccepted(byte b)
{
return (65 <= b && b <= 90) ||
(97 <= b && b <= 122) ||
b == 10 || b == 13 || b == 32;
}
arr.Where(IsAccepted).ToArray(); // equivalent to FilterText(arr)
private static bool被接受(字节b)
{
返回(65在大多数情况下,我同意@MarkByers。Linq的效率会比过程代码低一点。一般来说,缺陷可以追溯到表达式树的编译。然而,可读性和时间改进在99%的情况下是值得的。当遇到性能问题时,请进行基准测试、修改和重新基准测试rk
话虽如此,LINQ与lambdas和匿名委托关系非常密切。这些特性被谈论和经常被谈论,就好像它们是同一件事一样。有一些情况下,这些构造比过程代码更快。看起来你的示例可能就是其中之一。我将重写你的code如下:
private static byte [] FilterText2(byte[] arr) {
return arr.Where( a=> (a >= 65 && a <= 90) ||
(a >= 97 && a <= 122) ||
a == 10 || a == 13 || a == 32
).ToArray();
}
专用静态字节[]FilterText2(字节[]arr){
返回arr.Where(a=>(a>=65&&a=97&&a只需将aspallel()
添加到查询的开头。如果希望以牺牲某些性能为代价保留原始订单,还可以添加AsOrdered()
。例如,以下LINQ语句:
arr.Where(IsAccepted).ToArray();
可以写为:
arr.AsParallel().AsOrdered().Where(IsAccepted).ToArray();
您只需确保:
每一个好的命令式代码都比好的声明性代码更节省时间和空间,因为声明性代码必须转换为命令式代码(除了您拥有一台Prolog机器……您可能没有,因为您正在询问.Net:-))
但是,如果您可以用比使用循环更简单、更可读的方式使用LINQ解决问题,那么这是值得的
var actualPrices = allPrices
.Where(price => price.ValidFrom <= today && price.ValidTo >= today)
.Select(price => price.PriceInUSD)
.ToList();
var实际价格=所有价格
.Where(price=>price.ValidFrom=今天)
.Select(price=>price.PriceInUSD)
.ToList();
它是“一行”,第一眼就可以看出它在做什么。声明一个新集合,循环使用旧集合,编写if并向新集合添加内容都不是。因此,如果您不想节省每一毫秒(您可能不想这样做,因为您使用的是.Net而不是带有嵌入式ASM的C),这就是一个胜利.而且LINQ是高度优化的-有更多的代码基-一个用于集合,一个用于XML,一个用于SQL…,所以它通常不会慢很多。没有理由不使用它
一些LINQ表达式可以很容易地使用并行LINQ进行并行化,几乎是“免费的”(=没有更多的代码,但并行开销仍然存在,所以请考虑一下)。为什么有j
?只需使用Add
而不是Insert
,您就可以省去该计数器。您可能应该替换.Insert(j,
部分为。添加(
并删除j
计数器。是的,谢谢你,我刚刚修改了代码,甚至没有安排!而且,由于大多数字符将被保留,你应该用新列表(arr.Length)替换新列表()
。这将避免在列表变大时必须重新创建其内部结构。您不需要这样做。传递给列表(int)
构造函数的参数仅指示容量(在不调整大小的情况下可容纳的容量),而不是它实际能容纳多少。同意@Mark。使用linq会比调试代码花费更多的时间。除非你会调试复杂的linq查询,这可能也很棘手-这并不意味着我不会使用它,尽管+1:这一点很好。如果你需要对返回的序列进行进一步的筛选/排序/操作,那么最好将其作为可枚举
返回,而不使用ToArray()
@Douglas我想您的意思是IEnumerable
(Enumerable
是一个静态类),但另有约定。
var queryA = from num in numberList.AsParallel()
select ExpensiveFunction(num); //good for PLINQ
var queryB = from num in numberList.AsParallel()
where num % 2 > 0
select num; //not as good for PLINQ
var actualPrices = allPrices
.Where(price => price.ValidFrom <= today && price.ValidTo >= today)
.Select(price => price.PriceInUSD)
.ToList();