나는이 foreach
루프를 마지막 항목이에서 선택할 때 몇 가지 논리를 실행해야합니다 List
예 :
foreach (Item result in Model.Results)
{
//if current result is the last item in Model.Results
//then do something in the code
}
for 루프와 카운터를 사용하지 않고 어떤 루프가 마지막인지 알 수 있습니까?
답변
마지막 요소로 무언가를 해야하는 경우 (마지막 요소 와 다른 것이 아니라 LINQ를 사용하면 여기에서 도움이됩니다.
Item last = Model.Results.Last();
// do something with last
마지막 요소와 다른 것을 해야하는 경우 다음과 같은 것이 필요합니다.
Item last = Model.Results.Last();
foreach (Item result in Model.Results)
{
// do something with each item
if (result.Equals(last))
{
// do something different with the last item
}
else
{
// do something different with every item but the last
}
}
항목이에서 반환 한 항목과 동일하다는 것을 알 수 있도록 사용자 지정 비교기를 작성해야 할 수도 Last()
있습니다.
이 방법은 Last
컬렉션을 반복해야 할 수도 있으므로 주의해서 사용해야 합니다. 소규모 컬렉션에서는 문제가되지 않지만 크기가 커지면 성능에 영향을 줄 수 있습니다. 목록에 중복 항목이 포함되어 있으면 실패합니다. 이 경우 다음과 같은 것이 더 적절할 수 있습니다.
int totalCount = result.Count();
for (int count = 0; count < totalCount; count++)
{
Item result = Model.Results[count];
// do something with each item
if ((count + 1) == totalCount)
{
// do something different with the last item
}
else
{
// do something different with every item but the last
}
}
답변
좋은 구식 for 루프는 어떻습니까?
for (int i = 0; i < Model.Results.Count; i++) {
if (i == Model.Results.Count - 1) {
// this is the last item
}
}
또는 Linq와 foreach를 사용하십시오.
foreach (Item result in Model.Results)
{
if (Model.Results.IndexOf(result) == Model.Results.Count - 1) {
// this is the last item
}
}
답변
Last()
특정 유형을 사용 하면 전체 컬렉션을 통해 루프됩니다!
의미 foreach
하고 호출 Last()
하면 두 번 반복 됩니다! 큰 컬렉션에서는 피하고 싶습니다.
그런 다음 해결책은 do while
루프 를 사용하는 것입니다 .
using var enumerator = collection.GetEnumerator();
var last = !enumerator.MoveNext();
T current;
while (!last)
{
current = enumerator.Current;
//process item
last = !enumerator.MoveNext();
if(last)
{
//additional processing for last item
}
}
컬렉션 유형이 유형의 경우를 제외하고 그래서 기능은 모든 콜렉션 요소를 통해 반복됩니다.IList<T>
Last()
컬렉션이 랜덤 액세스 (예 : 구현 IList<T>
)를 제공하는 경우 다음과 같이 항목을 확인할 수도 있습니다.
if(collection is IList<T> list)
return collection[^1]; //replace with collection.Count -1 in pre-C#8 apps
답변
Chris가 보여 주듯이 Linq는 일할 것입니다. Last ()를 사용하여 열거 가능한 마지막 항목에 대한 참조를 얻으십시오. 해당 참조로 작업하지 않는 한 일반 코드를 수행하지만 해당 참조로 작업하는 경우 추가 작업을 수행하십시오. 단점은 항상 O (N) 복잡성이라는 것입니다.
대신 Count () (IEnumerable도 ICollection 인 경우 O (1)이며 대부분의 내장 IEnumerable에 해당되는 경우)를 사용하고 foreach를 카운터와 하이브리드로 사용할 수 있습니다.
var i=0;
var count = Model.Results.Count();
foreach (Item result in Model.Results)
{
if (++i == count) //this is the last item
}
답변
foreach (var item in objList)
{
if(objList.LastOrDefault().Equals(item))
{
}
}
답변
Shimmy가 지적했듯이 Last () 사용은 성능 문제가 될 수 있습니다. 예를 들어 컬렉션이 LINQ 식의 라이브 결과 인 경우입니다. 여러 번의 반복을 방지하기 위해 다음과 같이 “ForEach”확장 방법을 사용할 수 있습니다.
var elements = new[] { "A", "B", "C" };
elements.ForEach((element, info) => {
if (!info.IsLast) {
Console.WriteLine(element);
} else {
Console.WriteLine("Last one: " + element);
}
});
확장 방법은 다음과 같습니다 (추가 보너스로 인덱스와 첫 번째 요소를보고 있는지 여부도 알려줍니다).
public static class EnumerableExtensions {
public delegate void ElementAction<in T>(T element, ElementInfo info);
public static void ForEach<T>(this IEnumerable<T> elements, ElementAction<T> action) {
using (IEnumerator<T> enumerator = elements.GetEnumerator())
{
bool isFirst = true;
bool hasNext = enumerator.MoveNext();
int index = 0;
while (hasNext)
{
T current = enumerator.Current;
hasNext = enumerator.MoveNext();
action(current, new ElementInfo(index, isFirst, !hasNext));
isFirst = false;
index++;
}
}
}
public struct ElementInfo {
public ElementInfo(int index, bool isFirst, bool isLast)
: this() {
Index = index;
IsFirst = isFirst;
IsLast = isLast;
}
public int Index { get; private set; }
public bool IsFirst { get; private set; }
public bool IsLast { get; private set; }
}
}
답변
Daniel Wolf의 답변 을 더욱 향상 IEnumerable
시키면 다음과 같은 여러 반복 및 람다를 피하기 위해 다른 스택에 쌓을 수 있습니다.
var elements = new[] { "A", "B", "C" };
foreach (var e in elements.Detailed())
{
if (!e.IsLast) {
Console.WriteLine(e.Value);
} else {
Console.WriteLine("Last one: " + e.Value);
}
}
확장 메소드 구현 :
public static class EnumerableExtensions {
public static IEnumerable<IterationElement<T>> Detailed<T>(this IEnumerable<T> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
using (var enumerator = source.GetEnumerator())
{
bool isFirst = true;
bool hasNext = enumerator.MoveNext();
int index = 0;
while (hasNext)
{
T current = enumerator.Current;
hasNext = enumerator.MoveNext();
yield return new IterationElement<T>(index, current, isFirst, !hasNext);
isFirst = false;
index++;
}
}
}
public struct IterationElement<T>
{
public int Index { get; }
public bool IsFirst { get; }
public bool IsLast { get; }
public T Value { get; }
public IterationElement(int index, T value, bool isFirst, bool isLast)
{
Index = index;
IsFirst = isFirst;
IsLast = isLast;
Value = value;
}
}
}