簡體   English   中英

使用LINQ,如何為與模式“ q1,q2”等匹配的值過濾字符串列表?

[英]Using LINQ how do you filter a list of strings for values that match the pattern “q1, q2” etc.?

這應該是一個簡單的方法,但我正在尋找最佳答案,至少要兼顧性能和優雅。

我有一個字符串列表, 某些值的格式為q1,q2,q3等。

我想選擇這些。

這樣做的最佳方法是什么?

最好的答案是使用Regex或Jay Bazuzi的int.TryParse建議

作為快速示例,請在LINQPad中嘗試以下操作:

void Main()
{
    int n = 100;

    string[] a = {"q2", "q3", "b"};
    a = a.Concat(Enumerable.Repeat(0,n).Select(i => "qasd")).ToArray(); /* Random data */

    /* Regex Method */
    System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex("^q[0-9]+$");
    List<string> regMethod = a.Where(c => r.IsMatch(c)).ToList().Dump("Result");

    /* IsInteger Method */
    List<string> intMethod = a.Where(c => c.StartsWith("q") && IsInteger(c.Substring(1))).ToList().Dump("Result");

    /* int.TryParse Method suggest by Jay Bazuzi */
    int e = 0;
    List<string> parseMethod = a.Where(c => c.StartsWith("q") && int.TryParse(c.Substring(1), out e)).ToList().Dump("Result");
}

public static bool IsInteger(string theValue)
{
   try
   {
       Convert.ToInt32(theValue);
       return true;
   } 
   catch 
   {
       return false;
   }
}

嘗試一次注釋掉兩種方法之一,並嘗試不同n值的性能。

我的經驗(在我的Core 2 Duo筆記本電腦上)似乎表明:

n = 100. Regex takes about 0.003 seconds, IsInteger takes about 0.01 seconds
n = 1,000. Regex takes about 0.004 seconds, IsInteger takes about 0.07 seconds
n = 10,000. Regex takes about 0.007 seconds, IsInteger takes about 0.67 seconds
n = 100,000. Regex takes about 0.046 seconds, IsInteger takes about 6.9 seconds
n = 1,000,000. Regex takes about 0.42 seconds, IsInteger takes about 1 minute and 6 seconds

ParseMethod具有與Regex相同的性能(如果以內聯方式完成,與代碼示例中的速度略快,如果以單獨的方法(即,替換IsInteger方法主體)完成,則性能幾乎相同)。

注意:創建字符串的成本未考慮在內(如果需要,可以插入日期差異),但是兩種方法的成本相同

如果大多數鍵都不帶有'q'(從不調用IsInteger),則這些數字更接近,但是即使在這種情況下 ,Regex也一樣好或更好。

即(對於“ asdasd”而不是“ qasd”的填充字符串):

n = 100. Regex takes about 0.003 seconds, IsInteger takes about 0.003 seconds
n = 1,000. Regex takes about 0.004 seconds, IsInteger takes about 0.004 seconds
n = 10,000. Regex takes about 0.005 seconds, IsInteger takes about 0.005 seconds
n = 100,000. Regex takes about 0.023 seconds, IsInteger takes about 0.025 seconds
n = 1,000,000. Regex takes about 0.21 seconds, IsInteger takes about 0.22 seconds

同樣,ParseMethod具有與Regex相同的性能。

結論:使用Regex或TryParse,在最壞的情況下它將更快,否則將更快

但是,是否有更好/更快捷的方法從字符串集合中選擇int值? 也許以某種方式編譯速度更快的通用過濾器?

似乎您正在嘗試進行微優化,這意味着您將花費很多精力來使程序以相同的速度運行。 首先關注代碼的清晰度,然后優化實際速度較慢的代碼。

假設您已概要分析並發現這是您在實際場景中應用程序的瓶頸:

在非例外情況下使用例外情況很少(通常會降低性能)。 例如,請參見http://www.developerfusion.com/code/4650/validating-an-integer/

根據情況的限制,最好將IsInteger()更改為以下一項:

bool int.TryParse(string s, out int result);

(請參閱http://msdn.microsoft.com/zh-cn/library/system.int32.tryparse.aspx

要么:

Microsoft.VisualBasic.Information.IsNumeric(object expression)

(請參閱http://www.hanselman.com/blog/ExploringIsNumericForC.aspx

要么

x >= '0' && x < '9'

接着:

.Where(c => c[0] == 'q' && IsInteger(c[1]))

IsInteger的瓶頸可能是由於try-catch。

我嘗試用TryParse替換IsInteger,並且得到以下結果(n = 1,000,000):

正則表達式方法:540 ms

TryParse方法:537毫秒

我將以下代碼用於第二種方法:

Func<string, bool> lambda = (string c) => { Int32 temp; 
                                    return c.StartsWith("q") 
                                    && int.TryParse(c.Substring(1),out temp); };
List<string> intMethod = a.Where(lambda).ToList();

這個故事的寓意是...

盡管我通常更喜歡使用Regex,但是在這種簡單的字符串操作簡單的情況下,TryParse解決方案是完全可以接受的。 在性能方面,使用哪種方法並不重要,但不要使用異常處理來檢查某個字符串值是否為int!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM