#c# #list #generics
#c# #Список #общие сведения
Вопрос:
Есть ли необычный способ узнать, что вы находитесь в последнем цикле в списке, без использования счетчиков
List<string> myList = new List<string>() {"are", "we", "there", "yet"};
foreach(string myString in myList) {
// Is there a fancy way to find out here if this is the last time through?
}
Комментарии:
1. что вы пытаетесь сделать с последним элементом? Вы пытаетесь построить предложение и добавить знаки препинания в конце? Если это так, вы могли бы попробовать
string.Join(" ", myList.ToArray()) "."
2. нашел решение для вас, ваааааай внизу…
Ответ №1:
Нет, для этого вам придется использовать обычный for(int i=0; i<myList.Length; i ) { ... }
цикл.
Комментарии:
1. Спасибо, это был мой запасной вариант, но я хотел сначала убедиться, что я ничего не упустил.
Ответ №2:
Как насчет использования вместо цикла for?
List<string> myList = new List<string>() {"are", "we", "there", "yet"};
for (var i=0; i<myList.Count; i )
{
var myString = myList[i];
if (i==myList.Count-1)
{
// this is the last item in the list
}
}
foreach
полезно — но если вам нужно вести подсчет того, что вы делаете, или индексировать вещи по количеству, тогда просто вернитесь к старому доброму for
циклу.
Ответ №3:
Есть два способа, которыми я бы это сделал.
Во-первых, с for
циклом вместо foreach
for(int i = 0; i < myList.Count; i )
{
string myString = myList[i];
bool isLast = i == myList.Count - 1;
...
}
Или, если это необходимо для работы с перечислителями, измените порядок вещей. Обычно MoveNext
выполняется как элемент управления циклом while, но если мы сделаем это прямо в начале цикла, мы можем использовать его возврат, чтобы определить, находимся ли мы в конце списка или нет.
IEnumerator<string> enumerator = myList.GetEnumerator();
bool isLast = !enumerator.MoveNext();
while(!isLast)
{
string myString = enumerator.Current;
isLast = !enumerator.MoveNext();
...
}
Ответ №4:
Эффективного способа сделать это нет.
Просто используйте for
цикл и индекс. В любом случае это выполняется быстрее.
Ответ №5:
Ну … нет способа узнать это. Не так просто, как вы могли бы предположить. Структура данных списка — это просто способ упорядочить элементы один за другим. Но у вас нет способа сказать, является ли элемент последним элементом, просто используя foreach structure. Лучше всего использовать for structure со свойством count, чтобы узнать, попали ли вы в последний (или предыдущий) элемент.
var length = list.Count;
for (var idx = 0; idx < list.Count; idx )
{
if (idx == (length - 1))
{
// The last item. Do something
}
}
надеюсь, это поможет.
Ответ №6:
Нет, такого не существует, вам придется использовать счетчик, если вы хотите использовать foreach
.
Ответ №7:
Используйте for
operator вместо foreach
Ответ №8:
«Необычный» способ — поддерживать 1 элемент lookahead, но с какой стати вы этого хотите? Просто веду подсчет. Вот необычный способ. Нет счетчиков, нет проверки свойства Count. Все, что он использует, это перечислитель:
using System;
using System.Collections.Generic;
namespace Sandbox
{
class Program
{
enum ListPosition : byte
{
First = 0x01 ,
Only = First|Last ,
Middle = 0x02 ,
Last = 0x04 ,
Exhausted = 0x00 ,
}
private static void WalkList( List<int> numbers )
{
List<int>.Enumerator numberWalker = numbers.GetEnumerator();
bool currFetched = numberWalker.MoveNext();
int currValue = currFetched ? numberWalker.Current : default( int );
bool nextFetched = numberWalker.MoveNext();
int nextValue = nextFetched ? numberWalker.Current : default( int );
ListPosition position ;
if ( currFetched amp;amp; nextFetched ) position = ListPosition.First ;
else if ( currFetched amp;amp; ! nextFetched ) position = ListPosition.Only ;
else if ( ! currFetched ) position = ListPosition.Exhausted ;
else throw new InvalidOperationException( "Reached Unreachable Code. Hmmm...that doesn't seem quite right" );
while ( position != ListPosition.Exhausted )
{
string article = ( position==ListPosition.Middle?"a":"the" );
Console.WriteLine( " {0} is {1} {2} item in the list" , currValue , article , position );
currFetched = nextFetched ;
currValue = nextValue ;
nextFetched = numberWalker.MoveNext() ;
nextValue = nextFetched?numberWalker.Current:default( int ) ;
if ( currFetched amp;amp; nextFetched ) position = ListPosition.Middle ;
else if ( currFetched amp;amp; ! nextFetched ) position = ListPosition.Last ;
else if ( ! currFetched ) position = ListPosition.Exhausted ;
else throw new InvalidOperationException( "Reached Unreachable Code. Hmmm...that doesn't seem quite right" );
}
Console.WriteLine() ;
return ;
}
static void Main( string[] args )
{
List<int> list1 = new List<int>( new []{ 1 , } ) ;
List<int> list2 = new List<int>( new []{ 1 , 2 , } ) ;
List<int> list3 = new List<int>( new []{ 1 , 2 , 3 , } ) ;
List<int> list4 = new List<int>( new []{ 1 , 2 , 3 , 4 , } ) ;
Console.WriteLine( "List 1:" ) ; WalkList( list1 ) ;
Console.WriteLine( "List 2:" ) ; WalkList( list2 ) ;
Console.WriteLine( "List 3:" ) ; WalkList( list3 ) ;
Console.WriteLine( "List 4:" ) ; WalkList( list4 ) ;
return ;
}
}
}
Ответ №9:
Зависит от вашего определения «необычного». Это может соответствовать:
if (myList.Count > 0)
{
myList.Take(myList.Count - 1)).ForEach(myString => doSomething(myString));
doSomethingElse(myList.Last());
}
Мне это кажется близким к тому, что вы ищете. Обратите внимание, что это не очень высокопроизводительно, но коротко и довольно читаемо, по крайней мере, на мой взгляд. Вы также могли бы написать это таким образом:
if (myList.Count > 0)
{
foreach (string myString in myList.Take(myList.Count - 1))
{
doSomething(myString);
}
doSomethingElse(myList.Last());
}
Вот еще одна альтернатива, которую я бы счел наиболее очевидной, но это, вероятно, самый быстрый способ сделать это:
if (myList.Count > 0)
{
for (int i = 0; i < myList.Count - 1; i )
{
doSomething(myList[i]);
}
doSomethingElse(myList.Count - 1);
}