Foreach kullanan ilk öğeden başka bir öğeden yinelemeye başlamak mümkün müdür?


89

Kendi özel koleksiyonum (bir ağaç) için IEnumerable'ı uygulamayı düşünüyorum, böylece ağacımı geçmek için foreach'i kullanabilirim. Ancak bildiğim kadarıyla foreach her zaman koleksiyonun ilk öğesinden başlar. Foreach'in hangi elementten başlayacağını seçmek istiyorum. Foreach'in başladığı unsuru bir şekilde değiştirmek mümkün müdür?


1
En az şaşkınlık ilkesini takip ederdim: en.wikipedia.org/wiki/Principle_of_least_astonishment
ChaosPandion

İlk öğeden başlamazsanız, yineleyicinin davranışını nasıl tanımlarsınız? Sıranın sonuna geldiğinde ne olur? Daha sonra ilk öğeye geri dönüp kalan öğeler üzerinde yineleme yapıyor mu?
Dan J

@ ChaosPandion'un yorumu, bu sorularla nereye gittiğimi gösteriyor. :)
Dan J

Yanıtlar:


165

Evet. Aşağıdakileri yapın:

Collection<string> myCollection = new Collection<string>;

foreach (string curString in myCollection.Skip(3))
    //Dostuff

Skipgeçerli dizinden başlayarak belirlediğiniz sayıda belirlediğinizi atlayan bir IEnumerable işlevidir. Öte yandan, yalnızca ilk üçünü kullanmak isteseydiniz .Take:

foreach (string curString in myCollection.Take(3))

Hatta bunlar eşleştirilebilir, yani yalnızca 4-6 öğeyi istiyorsanız, şunları yapabilirsiniz:

foreach (string curString in myCollection.Skip(3).Take(3))

İyi karar. Stackoverflow'da WTB otomatik tamamlama (gahh bunun gerçek adını hatırlayamıyor)
MoarCodePlz

Bu gerçekten atlıyor mu yoksa sadece bir kopya mı oluşturuyor? IE bu ikisi farklı olurdu: foreach(List<string> row in rows.skip(1)){ row[0] = "newInfo"; } vs for(int i=1; i<rows.Count;i++){ List<string> row = rows[i]; row[0] = "newStuff"; }
TigerBear

25

SkipBelirli sayıda öğeyi atlamak için LINQ to Objects'teki yöntemi kullanmak en kolay yoldur :

foreach (var value in sequence.Skip(1)) // Skips just one value
{
    ...
}

Açıkçası, farklı sayıda öğeyi atlamak için başka herhangi bir değer için 1'i değiştirin ...

Benzer şekilde Take, döndürülen öğelerin sayısını sınırlamak için kullanabilirsiniz .

Edulinq blog dizimde bunların her ikisi (ve ilgili SkipWhileve TakeWhileyöntemler) hakkında daha fazla bilgi edinebilirsiniz .


Jon, eğer "dizi" Null ise bu bir istisna riskini taşımaz mı?
WEFX

@WEFX: sequenceMeşru olup olamayacağına dair hiçbir fikrimiz nullyok. Muhtemelen OP bunu kendi başına halledebilir - bu sorunun bir parçası değil ...
Jon Skeet

5

Bazı öğeleri atlamak ve oradan başlamasını sağlamak için Enumerable.Skip'i kullanabilirsiniz .

Örneğin:

foreach(item in theTree.Skip(9))  // Skips the first 9 items
{
    // Do something

Bununla birlikte, bir ağaç yazıyorsanız, ağaç öğesinin kendisinde IEnumerable<T>, oradan numaralandırılacak yeni bir tane döndürecek bir üye sağlamak isteyebilirsiniz . Bu, potansiyel olarak uzun vadede daha faydalı olacaktır.


Gibi bir şey IEnumerable<T> SubTree(rootIndex)? İyi karar!
Dan J

Cevabınız için teşekkürler, umut verici görünüyor, atla ile ilgili MSDN bilgilerini okurken, IEnumerable <MyTree> için bir genişletme yöntemi olacak bir StartFrom yöntemi (bu IEnumerable <MyTree> ağacı, MyTreeElement öğesi) yazmanın mümkün olduğu sonucuna vardım. yinelemeye başlamam gereken IEnumerable <MyTreeElement> döndürür. O zaman belki bu yöntemi foreach olarak kullanabilirim (tree.StartFrom (someElement) içindeki var element)).
cehennem

@inferno: Evet, bunu kolayca yapabilirsiniz. Bununla birlikte, MyTreeElement'e daha çok şuna benzer bir yöntem / özellik eklerdim IEnumerable<MyTreeElement> Children, böylece şunları yapabilirsiniz: foreach(var item in someElement.Children)- IMO uzantı yöntemlerini kullanmaktan çok daha net.
Reed Copsey

-1

Foreach koleksiyonunuzu, uygulamanızın belirlediği şekilde yineleyecek IEnumerable . Dolayısıyla, öğeleri atlayabilmenize rağmen (yukarıda önerildiği gibi), yine de teknik olarak öğeleri aynı sırayla yineliyorsunuz.

Neyi başarmaya çalıştığınızdan emin değilsiniz, ancak sınıfınızın IEnumerable, her biri öğeleri belirli bir sırayla numaralandıran birden çok özelliği olabilir .


-1

Bir satırdaki Satırları okumayı atlamak istiyorsanız DataGridView, bunu deneyin

foreach (DataGridViewRow row in dataGridView1.Rows.Cast<DataGridViewRow().Skip(3))

DataGridViewSatırları atlayarak birinin içeriğini diğerine kopyalamak istiyorsanız , şunu deneyin,

foreach (DataGridViewRow row in dataGridView1.Rows.Cast<DataGridViewRow>().Skip(3))
{
    foreach (DataGridViewCell cell in row.Cells)
    {
        string value = cell.Value.ToString();
        dataGridView2.Rows[i].Cells[j].Value = cell.Value.ToString();
        j++;
    }
    i++;
    j = 0;
}

bu, içeriği DataGridView3 satır atlayarak birinden diğerine kopyalar .


Bu, sorulan soruyu yanıtlamıyor - soruda hiç bahsedilmiyor DataGridView(hatta bir UI çerçevesi).
NightOwl888

@ NightOwl888 Bu soru cevaplandı çünkü soru bazı yinelemeleri atlamak ve foreach döngüsünde bundan sonra yineleme yapmaktı. Örneğimde DataGridView'e uygulamak için Skip () kullandım.
JUNED Han Momin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.