[Linq] استخدام لينق لتوصيل السلاسل



Answers

return string.Join(", ", strings.ToArray());

في .Net 4، هناك زائد جديد ل string.Join أن يقبل string.Join IEnumerable<string> . ستبدو التعليمات البرمجية كما يلي:

return string.Join(", ", strings);
Question

ما هي الطريقة الأكثر فعالية لكتابة المدرسة القديمة:

StringBuilder sb = new StringBuilder();
if (strings.Count > 0)
{
    foreach (string s in strings)
    {
        sb.Append(s + ", ");
    }
    sb.Remove(sb.Length - 2, 2);
}
return sb.ToString();

... في لينق؟




هل نظرت إلى طريقة الإضافة المجمعة؟

var sa = (new[] { "yabba", "dabba", "doo" }).Aggregate((a,b) => a + "," + b);



يمكنك الجمع بين لينق و string.join() بشكل فعال جدا. هنا أنا إزالة عنصر من سلسلة. هناك طرق أفضل للقيام بذلك أيضا ولكن هنا هو:

filterset = String.Join(",",
                        filterset.Split(',')
                                 .Where(f => mycomplicatedMatch(f,paramToMatch))
                       );



يمكنك استخدام StringBuilder في Aggregate :

  List<string> strings = new List<string>() { "one", "two", "three" };

  StringBuilder sb = strings
    .Select(s => s)
    .Aggregate(new StringBuilder(), (ag, n) => ag.Append(n).Append(", "));

  if (sb.Length > 0) { sb.Remove(sb.Length - 2, 2); }

  Console.WriteLine(sb.ToString());

( Select في هناك فقط لتظهر يمكنك أن تفعل المزيد من الأشياء لينق.)




فعلت التالية سريعة وقذرة عند تحليل ملف سجل إيس باستخدام لينق، وأنها عملت @ 1 مليون خطوط بشكل جيد جدا (15 ثانية)، على الرغم من أن حصلت على خطأ من الذاكرة عند محاولة 2 مليون خطوط.

    static void Main(string[] args)
    {

        Debug.WriteLine(DateTime.Now.ToString() + " entering main");

        // USED THIS DOS COMMAND TO GET ALL THE DAILY FILES INTO A SINGLE FILE: copy *.log target.log 
        string[] lines = File.ReadAllLines(@"C:\Log File Analysis\12-8 E5.log");

        Debug.WriteLine(lines.Count().ToString());

        string[] a = lines.Where(x => !x.StartsWith("#Software:") &&
                                      !x.StartsWith("#Version:") &&
                                      !x.StartsWith("#Date:") &&
                                      !x.StartsWith("#Fields:") &&
                                      !x.Contains("_vti_") &&
                                      !x.Contains("/c$") &&
                                      !x.Contains("/favicon.ico") &&
                                      !x.Contains("/ - 80")
                                 ).ToArray();

        Debug.WriteLine(a.Count().ToString());

        string[] b = a
                    .Select(l => l.Split(' '))
                    .Select(words => string.Join(",", words))
                    .ToArray()
                    ;

        System.IO.File.WriteAllLines(@"C:\Log File Analysis\12-8 E5.csv", b);

        Debug.WriteLine(DateTime.Now.ToString() + " leaving main");

    }

كان السبب الحقيقي الذي استخدمته لينق ل ديستنكت () أنا بحاجة إلى سابقا:

string[] b = a
    .Select(l => l.Split(' '))
    .Where(l => l.Length > 11)
    .Select(words => string.Format("{0},{1}",
        words[6].ToUpper(), // virtual dir / service
        words[10]) // client ip
    ).Distinct().ToArray()
    ;



بيانات الأداء السريع ل ستينغبيلدر مقابل تحديد حالة أكثر من 3000 العناصر:

وحدة الاختبار المدة (بالثواني) LINQ_SELECT 00: 00: 01.8012535
LINQ_StringBuilder 00: 00: 00.0036644

    [TestMethod()]
    public void LINQ_StringBuilder()
    {
        IList<int> ints = new List<int>();
        for (int i = 0; i < 3000;i++ )
        {
            ints.Add(i);
        }
        StringBuilder idString = new StringBuilder();
        foreach (int id in ints)
        {
            idString.Append(id + ", ");
        }
    }
    [TestMethod()]
    public void LINQ_SELECT()
    {
        IList<int> ints = new List<int>();
        for (int i = 0; i < 3000; i++)
        {
            ints.Add(i);
        }
        string ids = ints.Select(query => query.ToString()).Aggregate((a, b) => a + ", " + b);
    }



من خلال " طريقة لينق فائقة بارد " قد يكون الحديث عن الطريقة التي لينق يجعل البرمجة الوظيفية أكثر استساغة بكثير مع استخدام أساليب الإرشاد. أعني، السكر النحوي الذي يسمح بالوصول بالسلاسل بطريقة خطية بصريا (واحدة تلو الأخرى) بدلا من التعشيش (واحد داخل الآخر). فمثلا:

int totalEven = Enumerable.Sum(Enumerable.Where(myInts, i => i % 2 == 0));

يمكن كتابة مثل هذا:

int totalEven = myInts.Where(i => i % 2 == 0).Sum();

يمكنك أن ترى كيف يكون المثال الثاني أسهل للقراءة. يمكنك أن ترى أيضا كيف يمكن إضافة المزيد من الوظائف مع أقل من مشاكل المسافة البادئة أو أقفال إغلاق ليسبي التي تظهر في نهاية التعبير.

وهناك الكثير من الأجوبة الأخرى تقول أن String.Join هو الطريق للذهاب لأنه هو الأسرع أو أبسط لقراءة. ولكن إذا كنت تأخذ تفسير بلدي " طريقة لينق فائقة باردة " ثم الجواب هو استخدام String.Join ولكن يكون ملفوفة في أسلوب تمديد أسلوب لينق من شأنها أن تسمح لك لسلسلة String.Join بطريقة ارضاء بصريا. حتى إذا كنت تريد أن تكتب sa.Concatenate(", ") تحتاج فقط لخلق شيء من هذا القبيل:

public static class EnumerableStringExtensions
{
   public static string Concatenate(this IEnumerable<string> strings, string separator)
   {
      return String.Join(separator, strings);
   }
}

سيوفر هذا الرمز الذي هو أدفانتانت كالمكالمة المباشرة (على الأقل من حيث تعقيد الخوارزمية) وفي بعض الحالات قد يجعل الرمز أكثر قابلية للقراءة (اعتمادا على السياق) خاصة إذا كان الرمز الآخر في الكتلة يستخدم أسلوب الدالة بالسلاسل .




هنا هو استخدام لينق النقي كتعبير واحد:

static string StringJoin(string sep, IEnumerable<string> strings) {
  return strings
    .Skip(1)
    .Aggregate(
       new StringBuilder().Append(strings.FirstOrDefault() ?? ""), 
       (sb, x) => sb.Append(sep).Append(x));
}

ولها لعنة جميلة بسرعة!




Links