الحصول على مفتاح المصفوفة في حلقة "foreach".

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

  •  09-06-2019
  •  | 
  •  

سؤال

كيف يمكنني الحصول على مفتاح العنصر الحالي في ملف foreach حلقة في C#؟

على سبيل المثال:

بي أتش بي

foreach ($array as $key => $value)
{
    echo("$value is assigned to key: $key");
}

ما أحاول القيام به في C#:

int[] values = { 5, 14, 29, 49, 99, 150, 999 };

foreach (int val in values)
{
    if(search <= val && !stop)
    {
         // Set key to a variable
    }
}
هل كانت مفيدة؟

المحلول

طريقة غراوينولف هي الطريقة الأكثر وضوحًا والأداء للقيام بذلك باستخدام مصفوفة:

إما أن تستخدم حلقة for أو أنشئ متغيرًا مؤقتًا تقوم بزيادته في كل تمريرة.

والذي سيبدو بالطبع هكذا:

int[] values = { 5, 14, 29, 49, 99, 150, 999 };

for (int key = 0; key < values.Length; ++key)
  if (search <= values[key] && !stop)
  {
    // set key to a variable
  }

باستخدام .NET 3.5، يمكنك اتباع نهج أكثر وظيفية أيضًا، ولكنه أكثر تفصيلاً قليلاً في الموقع، ومن المرجح أن يعتمد على زوجين وظائف الدعم ل زيارة العناصر الموجودة في IEnumerable.المبالغة إذا كان هذا هو كل ما تحتاج إليه، ولكنه مفيد إذا كنت تميل إلى القيام بالكثير من عمليات معالجة التجميع.

نصائح أخرى

إذا كنت تريد الحصول على المفتاح (اقرأ:الفهرس) فسيتعين عليك استخدام حلقة for.إذا كنت تريد بالفعل الحصول على مجموعة تحتوي على مفاتيح/قيم، فسأفكر في استخدام HashTable أو قاموس (إذا كنت تريد استخدام الأدوية العامة).

Dictionary<int, string> items = new  Dictionary<int, string>();

foreach (int key in items.Keys)
{
  Console.WriteLine("Key: {0} has value: {1}", key, items[key]);
}

أتمنى أن يساعد ذلك ، تايلر

باستخدام DictionaryEntry وKeyValuePair:

مرتكز على
MSDN

IDictionary<string,string> openWith = new Dictionary<string,string>()
{
   { "txt", "notepad.exe" }
   { "bmp", "paint.exe" }
   { "rtf", "wordpad.exe" }
};

foreach (DictionaryEntry de in openWith)
{
    Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}

// also

foreach (KeyValuePair<string,string> de in openWith)
{
    Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
}

سؤال SO ذو صلة:KeyValuePair VS DictionaryEntry

للأسف لا توجد طريقة مدمجة للقيام بذلك.إما أن تستخدم حلقة for أو أنشئ متغيرًا مؤقتًا تقوم بزيادته في كل تمريرة.

لقد أجبت على هذا في نسخة أخرى من هذا السؤال:

Foreach هو التكرار على المجموعات التي تنفذ ienumerable.يقوم بذلك عن طريق الاتصال بـ GetEnumerator على المجموعة ، والتي ستعيد العداد.

هذا العداد لديه طريقة وخاصية:

* MoveNext()
* Current

إرجاع الحالي الكائن الذي يعمل فيه العداد حاليًا ، يقوم Movenext بتحديث الحالي إلى الكائن التالي.

من الواضح أن مفهوم الفهرس غريب على مفهوم التعداد ، ولا يمكن القيام به.

ولهذا السبب ، فإن معظم المجموعات قادرة على اجتيازها باستخدام مؤشر وبناء حلقة.

أنا أفضل استخدام حلقة في هذه الحالة مقارنة بتتبع الفهرس بمتغير محلي.

كيف يمكنك الحصول على فهرس التكرار الحالي لحلقة foreach؟

في الواقع، يجب عليك استخدام حلقة for (;;) الكلاسيكية إذا كنت تريد التكرار عبر مصفوفة.لكن الوظيفة المماثلة التي حققتها باستخدام كود PHP الخاص بك يمكن تحقيقها في C# مثل هذا باستخدام القاموس:

Dictionary<int, int> values = new Dictionary<int, int>();
values[0] = 5;
values[1] = 14;
values[2] = 29;
values[3] = 49;
// whatever...

foreach (int key in values.Keys)
{
    Console.WriteLine("{0} is assigned to key: {1}", values[key], key);
}

يمكنك تنفيذ هذه الوظيفة بنفسك باستخدام طريقة الامتداد.على سبيل المثال، فيما يلي تطبيق لطريقة الامتداد KeyValuePairs التي تعمل على القوائم:

public struct IndexValue<T> {
    public int Index {get; private set;}
    public T Value {get; private set;}
    public IndexValue(int index, T value) : this() {
        this.Index = index;
        this.Value = value;
    }
}

public static class EnumExtension
{
    public static IEnumerable<IndexValue<T>> KeyValuePairs<T>(this IList<T> list) {
        for (int i = 0; i < list.Count; i++)
            yield return new IndexValue<T>(i, list[i]);
    }
}

إليك الحل الذي توصلت إليه للتو لهذه المشكلة

الكود الأصلي:

int index=0;
foreach (var item in enumerable)
{
    blah(item, index); // some code that depends on the index
    index++;
}

رمز محدث

enumerable.ForEach((item, index) => blah(item, index));

طريقة التمديد:

    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumerable, Action<T, int> action)
    {
        var unit = new Unit(); // unit is a new type from the reactive framework (http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx) to represent a void, since in C# you can't return a void
        enumerable.Select((item, i) => 
            {
                action(item, i);
                return unit;
            }).ToList();

        return pSource;
    }

myKey = Array.IndexOf(values, val);

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