Policzyć przedmioty z liczby mnogiej bez iteracji?
private IEnumerable<string> Tables
{
get
{
yield return "Foo";
yield return "Bar";
}
}
Powiedzmy, że chcę iterate na tych i napisać coś takiego jak przetwarzanie #n Z # m.
Czy Jest jakiś sposób, aby dowiedzieć się wartości m bez iteracji przed moją główną iteracją?
Mam nadzieję, że wyraziłem się jasno.19 answers
IEnumerable
nie popiera tego. To z założenia. IEnumerable
używa leniwej oceny, aby uzyskać elementy, o które prosisz tuż przed ich potrzebą.
Jeśli chcesz znać liczbę elementów bez iteracji nad nimi, możesz użyć ICollection<T>
, ma ona właściwość Count
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-03 03:02:20
Metoda rozszerzenia System.Linq.Enumerable.Count
na IEnumerable<T>
ma następującą implementację:
ICollection<T> c = source as ICollection<TSource>;
if (c != null)
return c.Count;
int result = 0;
using (IEnumerator<T> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
result++;
}
return result;
Więc próbuje rzucić do ICollection<T>
, który ma właściwość Count
i używa tego, jeśli to możliwe. W przeciwnym razie iteruje.
Więc najlepiej jest użyć metody rozszerzenia Count()
na swoim obiekcie IEnumerable<T>
, ponieważ w ten sposób uzyskasz najlepszą możliwą wydajność.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-02 01:20:57
Dodam jeszcze jakieś info:
Rozszerzenie Count()
nie zawsze jest iteracyjne. Rozważ LINQ do Sql, gdzie licznik trafia do bazy danych, ale zamiast przywracać wszystkie wiersze, wydaje polecenie SQL Count()
i zwraca ten wynik.
Dodatkowo kompilator (lub runtime) jest na tyle inteligentny, że wywoła metodę objects Count()
, jeśli taką posiada. Więc to nie jak mówią inni, bycie całkowicie ignorantem i zawsze powtarzanie, aby liczyć żywioły.
W wielu przypadkach, gdy programista tylko sprawdza if( enumerable.Count != 0 )
używając metody rozszerzenia Any()
, jak w if( enumerable.Any() )
jest o wiele bardziej wydajny z leniwą oceną linq, ponieważ może zwarć, gdy może określić, że są jakieś elementy. Jest również bardziej czytelny
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-29 17:18:31
Liczba nie może liczyć bez iteracji.
W "normalnych" okolicznościach, klasy implementujące IEnumerable lub IEnumerable
Raczej Count jest to metoda rozszerzenia, zdefiniowana na statycznej klasie Enumerable. Oznacza to, że może być wywołana na dowolnej instancji klasy pochodnej IEnumerable
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 21:40:29
Mój przyjaciel ma serię postów na blogu, które dostarczają ilustracji, dlaczego nie możesz tego zrobić. Tworzy funkcję, która zwraca liczbę mnogą, gdzie każda iteracja zwraca następną liczbę pierwszą, aż do ulong.MaxValue
, a następny element nie jest obliczany, dopóki o niego nie poprosisz. Szybkie, pop pytanie: ile przedmiotów jest zwracanych?
Tutaj są posty, ale są trochę długie:
- Beyond Loops (zapewnia początkową klasę Enumerable, używaną w drugiej posts)
- Applications of Iterate (Initial implementation)
- szalone metody rozszerzania: ToLazyList (Optymalizacja wydajności)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-04 15:10:07
Nie, Nie w ogóle. Jednym z punktów korzystania z wyliczeń jest to, że rzeczywisty zbiór obiektów w wyliczeniu nie jest znany (z góry, lub nawet w ogóle).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 21:07:40
Możesz użyć systemu.Linq.
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
private IEnumerable<string> Tables
{
get {
yield return "Foo";
yield return "Bar";
}
}
static void Main()
{
var x = new Test();
Console.WriteLine(x.Tables.Count());
}
}
Otrzymasz wynik '2'.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-26 19:02:13
Alternatywnie możesz wykonać następujące czynności:
Tables.ToList<string>().Count;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-24 05:50:43
Wychodząc poza twoje bezpośrednie pytanie (na które dokładnie odpowiedziałeś negatywnie), jeśli chcesz zgłosić postęp podczas przetwarzania wyliczenia, możesz zajrzeć do mojego posta na blogu raportowanie postępu podczas zapytań Linq .
Pozwala ci to zrobić:
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += (sender, e) =>
{
// pretend we have a collection of
// items to process
var items = 1.To(1000);
items
.WithProgressReporting(progress => worker.ReportProgress(progress))
.ForEach(item => Thread.Sleep(10)); // simulate some real work
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 15:56:18
Użyłem takiego sposobu wewnątrz metody, aby sprawdzić przekazaną w IEnumberable
treść
if( iEnum.Cast<Object>().Count() > 0)
{
}
Wewnątrz takiej metody:
GetDataTable(IEnumberable iEnum)
{
if (iEnum != null && iEnum.Cast<Object>().Count() > 0) //--- proceed further
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-29 07:46:52
To zależy od wersji. Net i implementacji Twojego obiektu. Microsoft naprawił liczbę mnogą.Metoda Count do sprawdzania implementacji i używa ICollection.Count lub ICollection.Count, zobacz szczegóły tutaj https://connect.microsoft.com/VisualStudio/feedback/details/454130
I poniżej jest MSIL z Ildasm dla systemu.Rdzeń, w którym System.Linq rezyduje.
.method public hidebysig static int32 Count<TSource>(class
[mscorlib]System.Collections.Generic.IEnumerable`1<!!TSource> source) cil managed
{
.custom instance void System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
// Code size 85 (0x55)
.maxstack 2
.locals init (class [mscorlib]System.Collections.Generic.ICollection`1<!!TSource> V_0,
class [mscorlib]System.Collections.ICollection V_1,
int32 V_2,
class [mscorlib]System.Collections.Generic.IEnumerator`1<!!TSource> V_3)
IL_0000: ldarg.0
IL_0001: brtrue.s IL_000e
IL_0003: ldstr "source"
IL_0008: call class [mscorlib]System.Exception System.Linq.Error::ArgumentNull(string)
IL_000d: throw
IL_000e: ldarg.0
IL_000f: isinst class [mscorlib]System.Collections.Generic.ICollection`1<!!TSource>
IL_0014: stloc.0
IL_0015: ldloc.0
IL_0016: brfalse.s IL_001f
IL_0018: ldloc.0
IL_0019: callvirt instance int32 class [mscorlib]System.Collections.Generic.ICollection`1<!!TSource>::get_Count()
IL_001e: ret
IL_001f: ldarg.0
IL_0020: isinst [mscorlib]System.Collections.ICollection
IL_0025: stloc.1
IL_0026: ldloc.1
IL_0027: brfalse.s IL_0030
IL_0029: ldloc.1
IL_002a: callvirt instance int32 [mscorlib]System.Collections.ICollection::get_Count()
IL_002f: ret
IL_0030: ldc.i4.0
IL_0031: stloc.2
IL_0032: ldarg.0
IL_0033: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<!!TSource>::GetEnumerator()
IL_0038: stloc.3
.try
{
IL_0039: br.s IL_003f
IL_003b: ldloc.2
IL_003c: ldc.i4.1
IL_003d: add.ovf
IL_003e: stloc.2
IL_003f: ldloc.3
IL_0040: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_0045: brtrue.s IL_003b
IL_0047: leave.s IL_0053
} // end .try
finally
{
IL_0049: ldloc.3
IL_004a: brfalse.s IL_0052
IL_004c: ldloc.3
IL_004d: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0052: endfinally
} // end handler
IL_0053: ldloc.2
IL_0054: ret
} // end of method Enumerable::Count
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 00:13:02
Oto wielka dyskusja na temat leniwej oceny i odroczonej realizacji . Zasadniczo musisz zmaterializować listę, aby uzyskać tę wartość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 15:41:50
Wynik liczby mnogiej.Funkcja Count() może być błędna. Jest to bardzo prosta próbka do przetestowania:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var test = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
var result = test.Split(7);
int cnt = 0;
foreach (IEnumerable<int> chunk in result)
{
cnt = chunk.Count();
Console.WriteLine(cnt);
}
cnt = result.Count();
Console.WriteLine(cnt);
Console.ReadLine();
}
}
static class LinqExt
{
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int chunkLength)
{
if (chunkLength <= 0)
throw new ArgumentOutOfRangeException("chunkLength", "chunkLength must be greater than 0");
IEnumerable<T> result = null;
using (IEnumerator<T> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
result = GetChunk(enumerator, chunkLength);
yield return result;
}
}
}
static IEnumerable<T> GetChunk<T>(IEnumerator<T> source, int chunkLength)
{
int x = chunkLength;
do
yield return source.Current;
while (--x > 0 && source.MoveNext());
}
}
}
Wynik musi być (7,7,3,3), ale rzeczywisty wynik to (7,7,3,17)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-12 16:41:30
Jedynym sposobem na szybkie liczenie jest, gdy oryginalna kolekcja ma indekser (jak tablica). Aby stworzyć ogólny kod z minimalnym wymaganiem, możesz użyć IEnumerable, ale jeśli potrzebujesz również liczby, moim preferowanym sposobem jest użycie tego interfejsu:
public interface IEnumAndCount<out T> : IEnumerable<T>
{
int Count { get; }
}
Jeśli oryginalna kolekcja nie ma żadnego indeksatora, implementacja Count może iterować nad kolekcją, ze znanym trafieniem w wydajności O (n).
Jeśli nie chcesz używać czegoś podobnego do / Align = "left" / LinearPolicz z powodów podanych przez Daniela Earwickera na początku tego pytania.
Powodzenia !Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-10 17:39:53
Nie.
Czy widzisz, że informacje są dostępne w kodzie, który napisałeś?
Można by argumentować, że kompilator "widzi", że są tylko dwa, ale oznaczałoby to, że musiałby analizować każdą metodę iteratora szukając tylko tego konkretnego patologicznego przypadku. A nawet gdyby tak było, jak byś to przeczytał, biorąc pod uwagę granice liczby mnogiej?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 21:10:41
Proponuję zadzwonić do Tolista. Tak, robisz wyliczenie wcześniej, ale nadal masz dostęp do listy pozycji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-04 05:00:20
Może nie daje to najlepszej wydajności, ale możesz użyć LINQ, aby policzyć elementy w liczbie mnogiej:
public int GetEnumerableCount(IEnumerable Enumerable)
{
return (from object Item in Enumerable
select Item).Count();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-26 08:39:09
Używam IEnum<string>.ToArray<string>().Length
i działa dobrze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-18 09:58:00
Używam takiego kodu, jeśli mam listę ciągów:
((IList<string>)Table).Count
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-07 10:27:49