Skaičiuokite elementus iš IEnumerable <t> be iteracijos?

 private IEnumerable<string> Tables { get { yield return "Foo"; yield return "Bar"; } } 

Tarkime, noriu juos pakartoti ir rašyti kažką panašaus į #n apdorojimą iš #m.

Ar yra būdas sužinoti m vertę be iteracijos iki mano pagrindinio iteracijos?

Tikiuosi, kad suprantu.

262
04 окт. nustatyti sebagomez 04 oct. 2008-10-04 00:05 '08 at 0:05 2008-10-04 00:05
@ 20 atsakymų

IEnumerable “ to nepalaiko. Tai pagal dizainą. IEnumerable naudoja tingų vertinimų, kad gautų pageidaujamus elementus prieš juos reikia.

Jei norite žinoti elementų skaičių be iteracijos per juos, galite naudoti „ ICollection<T> , jis turi „ Count ICollection<T> .

271
04 окт. Atsakymą Mendelt pateikė spalio 4 d 2008-10-04 00:08 '08 at 0:08 2008-10-04 00:08

System.Linq.Enumerable.Count išplėtimo metodas „ IEnumerable<T> turi tokį įgyvendinimą:

 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; 

Todėl jis bando naudoti „ ICollection<T> , turinčią „ Count savybę, ir, jei įmanoma, naudoja jį. Priešingu atveju ji kartojasi.

Taigi, geriausia naudoti „ IEnumerable<T> objektą„ Count() pratęsimo metodą, nes tokiu būdu gausite maksimalų našumą.

171
12 мая '09 в 18:48 2009-05-12 18:48 atsakė Daniel Earwicker , gegužės 12 d

Tiesiog pridėkite papildomos informacijos:

Count() plėtinys ne visada kartojasi. Apsvarstykite „Linq“ į „SQL“, kur skaičius eina į duomenų bazę, bet vietoj to, kad grąžinamos visos eilutės, ji išleidžia komandą „Sql Count() ir grąžina šį rezultatą.

Be to, kompiliatorius (arba vykdymo aplinka) yra pakankamai protingas, kad būtų galima paskambinti Count() metodas objektams, jei yra. Taigi kiti respondentai sako, kad tai visiškai nežino ir visada kartojasi, kad būtų galima suskaičiuoti elementus.

Daugeliu atvejų, kai programuotojas paprasčiausiai patikrina, if( enumerable.Count != 0 ) naudoja Any() išplėtimo metodą, kaip ir ( if( enumerable.Any() ) , jis yra daug efektyvesnis, kai yra tingus linq įvertinimas, nes jis gali būti trumpas, kai tik bus Jis galės nustatyti, ar yra kokių nors elementų, jis taip pat yra aiškesnis.

73
04 окт. Robert Paulson atsakymas spalio 4 d 2008-10-04 06:49 '08 at 6:49 2008-10-04 06:49

Mano draugas turi keletą dienoraščio įrašų, kurie iliustruoja, kodėl negalite to padaryti. Jis sukuria funkciją, kuri grąžina IEnumerable, kur kiekvienas iteracija grąžina kitą pirminį skaičių iki ulong.MaxValue , o kitas elementas nėra apskaičiuojamas tol, kol neprašysite. Greitas ir iškylantis klausimas: kiek elementų grąžinama?

Štai pranešimai, tačiau jie yra ilgi:

9
04 окт. atsakymą pateikė Joel Coehoorn 04 spalis 2008-10-04 00:18 '08 at 12:18 2008-10-04 00:18

„IEnumerable“ negali skaičiuoti be pakartojimo.

„Normaliomis“ aplinkybėmis galite įdiegti klases, kurios įgyvendina IEnumerable arba IEnumerable <T>, pvz., „List <T>“, kad įgyvendintų skaičiavimo metodą grąžindami sąrašą <T>. Tačiau skaičiavimo metodas iš tikrųjų nėra IEnumerable <T> arba IEnumerable. (Vienintelis, kuris iš tikrųjų yra „GetEnumerator“.) Ir tai reiškia, kad klasės įgyvendinimas negali būti įgyvendintas.

Atvirkščiai, skaičiavimas yra pratęsimo metodas, apibrėžtas statinėje klasėje Skaičiuojamas. Tai reiškia, kad jis gali būti vadinamas bet kuriuo „IEnumerable <T>“ išvestinės klasės egzemplioriumi, neatsižvelgiant į šios klasės įgyvendinimą. Tačiau tai taip pat reiškia, kad ji įgyvendinama vienoje vietoje, ne vienoje iš šių klasių. Tai, žinoma, reiškia, kad jis turi būti įgyvendintas taip, kad būtų visiškai nepriklausomas nuo šios klasės vidinių komponentų. Vienintelis būdas skaičiuoti yra per iteraciją.

9
04 окт. Chris Ammerman atsakymas, pateiktas 04 spalį 2008-10-04 00:40 '08 0:40 2008-10-04 00:40

Galite naudoti System.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()); } } 

Jūs gausite rezultatą "2".

8
26 янв. Atsakymas pateikiamas prosseek, sausio 26 d 2012-01-26 22:02 '12 10:02 pm 2012-01-26 22:02

Ne, ne apskritai. Vienas iš sąrašų panaudojimo taškų yra tas, kad faktinis objektų skaičius sąraše yra nežinomas (iš anksto arba net apskritai).

8
04 окт. atsakymą pateikė JesperE 04 oct. 2008-10-04 00:07 '08 at 0:07 2008-10-04 00:07

Arba galite atlikti šiuos veiksmus:

 Tables.ToList<string>().Count; 
7
12 мая '09 в 18:35 2009-05-12 18:35 atsakymas pateikiamas h_alsharaf gegužės 12 d., 09:35, 2009-05-12 18:35

Jei norite pranešti apie pažangą, susijusią su išvardytų elementų apdorojimu, gali tekti peržiūrėti mano dienoraščio įrašą „ Ataskaitos“ per „Linq“ užklausas , jei atsakysite į neigiamą atsakymą.

Tai leidžia jums tai padaryti:

 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 }; 
5
12 мая '09 в 18:56 2009-05-12 18:56 atsakymas į Samuel Jack'ą pateiktas gegužės 12 d. 09:18 val. 2009-05-12 18:56

IEnumberable metodą naudoju metode, kad IEnumberable patikrinti, ar turinys perduodamas IEnumberable

 if( iEnum.Cast<Object>().Count() > 0) { } 

Tokio metodo viduje:

 GetDataTable(IEnumberable iEnum) { if (iEnum != null  iEnum.Cast<Object>().Count() > 0) //--- proceed further } 
4
02 нояб. Atsakymas duotas Shahidul Haque 02 lapkričio. 2012-11-02 10:58 '12 at 10:58 2012-11-02 10:58

Tai priklauso nuo to, kokia .Net versija ir jūsų „IEnumerable“ diegimas. „Microsoft“ įdiegė „IEnumerable.Count“ metodą, kad patvirtintų įgyvendinimą ir naudoja ICollection.Count arba ICollection <TSource> .Skaičius, žr. Išsamią informaciją čia https://connect.microsoft.com/VisualStudio/feedback/details/454130

Ir toliau yra MSIL iš Ildasm sistemai.Core, kuriame yra System.Linq.

 .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 
3
25 апр. atsakymas pateikiamas 25 Bal 2011-04-25 08:18 '11 at 8:18 2011-04-25 08:18

Negalite to padaryti be vidinio iteracijos. Jis veiks.

 using System.Linq; ... Tables.Count(); 
2
18 мая '16 в 0:42 2016-05-18 00:42 atsakymą įteikė Carlosas Toledo , gegužės 18 d. 16 d. 0:42 2016-05-18 00:42

Funkcijos IEnumerable.Count () rezultatas gali būti neteisingas. Tai labai paprastas bandymo pavyzdys:

 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()); } } } 

Rezultatas turėtų būti (7,7,3,3), bet faktinis rezultatas - (7,7,3,17)

2
12 авг. Atsakymas pateikiamas Romano Golubino 12 d. 2009-08-12 19:41 '09, 7:41 val. 2009-08-12 19:41

Čia yra puiki diskusija apie tingų vertinimą ir atidėjimą . Iš esmės jūs turite įvykdyti sąrašą, kad gautumėte šią vertę.

2
12 мая '09 в 18:41 2009-05-12 18:41 atsakymą pateikė JP Alioto gegužės 12 d., 09:18, 2009-05-12 18:41

Vienintelis būdas gauti greitą skaičiavimą yra tada, kai šaltinio kolekcija turi indeksą (pavyzdžiui, masyvą). Jei norite sukurti bendrąjį kodą su minimaliais reikalavimais, galite naudoti „IEnumerable“, tačiau jei jums reikia paskyros, norėčiau naudoti šią sąsają:

 public interface IEnumAndCount<out T> : IEnumerable<T> { int Count { get; } } 

Jei jūsų pradinėje kolekcijoje nėra indeksuotojo, jūsų skaičiaus įgyvendinimas gali kartoti per kolekciją gerai žinomu O (n) našumo rezultatu.

Jei nenorite naudoti kažko panašaus į „IEnumAndCount“, geriausia eiti su „Linq.Count“ dėl priežasčių, kurias pateikė Daniel Ervicker.

Sėkmės!

1
20 сент. Atsakymą pateikė Eric Ouellet, rugsėjo 20 d 2011-09-20 20:57 '11 prie 20:57 2011-09-20 20:57

Siūlyčiau paskambinti „ToList“. Taip, jūs darote šį įrašą anksčiau, bet vis tiek turite prieigą prie savo prekių sąrašo.

0
04 окт. Jonathano Alleno atsakymas 04 sp 2008-10-04 08:00 '08, 8:00, 2008-10-04 08:00

Ne

Ar matote šią informaciją bet kurioje jūsų parašyto kodo vietoje?

Galima teigti, kad kompiliatorius gali „matyti“, kad yra tik du iš jų, tačiau tai reikštų, kad reikės analizuoti kiekvieną iteratoriaus metodą, kuris vertina šį konkretų patologinį atvejį. Ir net jei taip būtų, kaip jūs jį perskaitytumėte, atsižvelgiant į IE skaičių skaičių?

0
04 окт. James Curran atsakymas, pateiktas 04 spalį 2008-10-04 00:10 '08 ne 0:10 2008-10-04 00:10

Tai gali jums nesuteikti geresnių rezultatų, tačiau galite naudoti LINQ, kad galėtumėte suskaičiuoti elementus IEskaitant:

 public int GetEnumerableCount(IEnumerable Enumerable) { return (from object Item in Enumerable select Item).Count(); } 
0
26 июня '13 в 11:39 2013-06-26 11:39 atsakymą įteikė Hugo birželio 26 d. 13 val. 11:39 2013-06-26 11:39

Aš naudoju IEnum<string>.ToArray<string>().Length , jis veikia gerai.

-2
18 янв. Atsakyti Oliver Kötter 18 jan. 2012-01-18 12:51 '12 12:51 2012-01-18 12:51

Naudoju šį kodą, jei turiu styginių sąrašą:

 ((IList<string>)Table).Count 
-2
07 мая '18 в 11:28 2018-05-07 11:28 atsakymas yra duotas „ Me Hungry “ gegužės 07 d. 18 val. 11:28 2018-05-07 11:28

Kiti klausimai apie arba Ask a Question