الحصول على مجموعة من القيم مؤشر باستخدام استعلام LINQ

StackOverflow https://stackoverflow.com/questions/237377

سؤال

هل هناك طريقة أفضل للقيام بذلك؟

string[] s = {"zero", "one", "two", "three", "four", "five"};

var x = 
s
.Select((a,i) => new {Value = a, Index = i})
.Where(b => b.Value.StartsWith("t"))
.Select(c => c.Index);

وأي بمعنى. أنا أبحث عن وسيلة أكثر كفاءة أو أكثر أناقة للحصول على وظائف البنود المطابقة للمعايير.

هل كانت مفيدة؟

المحلول

هل يمكن بسهولة إضافة طريقة تمديد الخاص بك:

public static IEnumerable<int> IndexesWhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    int index=0;
    foreach (T element in source)
    {
        if (predicate(element))
        {
            yield return index;
        }
        index++;
    }
}

وثم استخدامه مع:

string[] s = {"zero", "one", "two", "three", "four", "five"};
var x = s.IndexesWhere(t => t.StartsWith("t"));

نصائح أخرى

إذا كنت فقط باستخدام المثال باعتبارها وسيلة لتعلم LINQ، تجاهل هذا المنصب.


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

string[] s = {"zero", "one", "two", "three", "four", "five"};
List<int> matchingIndices = new List<int>();

for (int i = 0; i < s.Length; ++i) 
{
   if (s[i].StartWith("t"))
   {
      matchingIndices.Add(i);
   }
}

ويبدو غرامة بالنسبة لي. قد حفظ الأحرف زوجين عن طريق تغيير حدد ل:

.Select((Value, Index) => new {Value, Index})

وهناك أيضا طريقة FindIndex في قائمة مجموعة التي تقوم بإنشاء طريقة الحذف الذي يمكن أن يعود المؤشر من المجموعة. يمكنك الرجوع إلى الرابط التالي في MSDN http://msdn.microsoft.com /en-us/library/x1xzf2ca.aspx .

وماذا عن هذا؟ انها تشبه إلى المرسل الأصلي ولكن أنا أولا تحديد المؤشرات وثم بناء مجموعة والذي يطابق المعايير.

var x = s.Select((a, i) => i).Where(i => s[i].StartsWith("t"));

وهذا هو صبي أقل كفاءة من بعض الإجابات الأخرى كما كرر قائمة بالكامل على مرتين.

وناقشت هذه المشكلة مثيرة للاهتمام مع زميل له وفي البداية اعتقدت حل JonSkeet كان كبيرا، لكنه أشار زميلي من مشكلة واحدة، وهي أنه إذا كانت وظيفة هي امتداد لIEnumerable<T>، ومن ثم يمكن أن تستخدم فيها مجموعة ينفذ ذلك .

ومع مجموعة، فإنه من الأسلم أن نقول ستحترم ترتيب المنتجة مع foreach (أي foreach وتكرار من الأول إلى الأخير)، ولكن ذلك لن يكون بالضرورة هو الحال مع مجموعات أخرى (قائمة، قاموس، الخ)، حيث سوف foreach لا تعكس <م> بالضرورة "النظام من الدخول". ومع ذلك، فإن وظيفة هناك، وأنه يمكن أن يكون مضللا.

في النهاية، انتهى بي الأمر مع شيء مماثل لإجابة tvanfosson، ولكن كطريقة التمديد، لصفائف:

public static int[] GetIndexes<T>(this T[]source, Func<T, bool> predicate)
{
    List<int> matchingIndexes = new List<int>();

    for (int i = 0; i < source.Length; ++i) 
    {
        if (predicate(source[i]))
        {
            matchingIndexes.Add(i);
        }
    }
    return matchingIndexes.ToArray();
}

وهنا تأمل سوف List.ToArray تحترم أجل العملية الأخيرة ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top