foreach с универсальным Списком, обнаруживая первое повторение при использовании типа значения

18
задан Richard Everett 7 January 2009 в 15:42
поделиться

7 ответов

Ну, Вы могли кодировать его с помощью явного повторения:

using(var iter = ints.GetEnumerator()) {
  if(iter.MoveNext()) {
     // do "first" with iter.Current

     while(iter.MoveNext()) {
       // do something with the rest of the data with iter.Current
     }
  }
}

опция флага bool (с foreach), вероятно, легче, хотя..., именно это я (почти) всегда делаю!

Другая опция была бы LINQ:

if(ints.Any()) {
  var first = ints.First();
  // do something with first
}

foreach(var item in ints.Skip(1)) {
  // do something with the rest of them
}

оборотная сторона вышеупомянутого - то, что оно пытается посмотреть на список 3 раза..., так как мы знаем, что это - список, который прекрасен - но если бы все, что мы имели, было IEnumerable<T>, то только было бы разумно выполнить итерации его однажды (так как источник не мог бы быть перечитаемым).

28
ответ дан 30 November 2019 в 06:36
поделиться

Только что я записал SmartEnumerable (часть MiscUtil), который сообщает, является ли элемент тока первым или последним, а также его индекс. Это может помочь Вам... это - часть MiscUtil, который является открытым исходным кодом - можно взять просто SmartEnumerable в соответствии с той же лицензией, конечно.

Пример кода (c'n'p от веб-страницы):

using System;
using System.Collections.Generic;

using MiscUtil.Collections;

class Example
{
    static void Main(string[] args)
    {
        List<string> list = new List<string>();
        list.Add("a");
        list.Add("b");
        list.Add("c");
        list.Add("d");
        list.Add("e");

        foreach (SmartEnumerable<string>.Entry entry in
                 new SmartEnumerable<string>(list))
        {
            Console.WriteLine ("{0,-7} {1} ({2}) {3}",
                               entry.IsLast  ? "Last ->" : "",
                               entry.Value,
                               entry.Index,
                               entry.IsFirst ? "<- First" : "");
        }
    }
}

РЕДАКТИРОВАНИЕ: Обратите внимание, что, в то время как это работает со ссылочными типами с отличными ссылками, это все еще перестанет работать, если Вы дадите ему список, где первая ссылка неожиданно возникает в другом месте в списке.

10
ответ дан 30 November 2019 в 06:36
поделиться

Так как Вы уже используете LINQ, Вы могли сделать это:

var list = new List<Int32>();

// do something with list.First();

foreach (var item in list.Skip(1))
{
    // do other stuff
}
2
ответ дан 30 November 2019 в 06:36
поделиться
foreach(int i in ints.Take(1))
{
 //do first thing
}

foreach(int i in ints.Skip(1))
{
  //do other things
}
7
ответ дан 30 November 2019 в 06:36
поделиться

Проблема, которую Вы имеете, - то, потому что равенство для типов значения основано на фактическом значении, не самой ссылке. А именно, в Вашем примере Ваш список, все обнуляет, таким образом, его выяснение, если currentItem == firstItem, и так как они - оба нуль, это всегда верно. Для такого рода вещи я всегда волновал использование булева флага.

1
ответ дан 30 November 2019 в 06:36
поделиться

Вместо того, если (i == ints.First()), это работает, если Вы используете if (i.Equals(ints.First())?

0
ответ дан 30 November 2019 в 06:36
поделиться

Если Вы действительно не хотите использовать булевскую переменную, Вы могли бы сделать что-то как:

List<int> ints = new List<int> { 0, 0, 0, 0 };

System.Diagnostics.Debug.WriteLine("First int - do something special" + ints.FirstOrDefault().ToString());
foreach (int i in ints.Skip(1))
{
    {
        System.Diagnostics.Debug.WriteLine("int Do something else");
    }
}

, Но это кажется немного.. странный :)

0
ответ дан 30 November 2019 в 06:36
поделиться