Apakah mungkin untuk memulai iterasi dari elemen selain yang pertama menggunakan foreach?

89

Saya berpikir tentang menerapkan IEnumerable untuk koleksi kustom saya (pohon) sehingga saya dapat menggunakan foreach untuk melintasi pohon saya. Namun setahu saya masing-masing selalu dimulai dari koleksi elemen pertama. Saya ingin memilih dari elemen mana masing-masing dimulai. Apakah mungkin untuk mengubah elemen dari mana foreach dimulai?

neraka
sumber
1
Saya akan mengikuti prinsip paling tidak keheranan: en.wikipedia.org/wiki/Principle_of_least_astonishment
ChaosPandion
Jika Anda tidak memulai dari elemen pertama, bagaimana Anda mendefinisikan perilaku iterator? Apa yang terjadi ketika mencapai akhir urutan? Apakah itu kemudian kembali ke elemen pertama dan mengulangi elemen yang tersisa?
Dan J
Komentar @ ChaosPandion adalah tujuan saya dengan pertanyaan-pertanyaan itu. :)
Dan J

Jawaban:

165

Iya. Lakukan hal berikut:

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

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

Skipadalah fungsi IEnumerable yang melewatkan berapa pun yang Anda tentukan mulai dari indeks saat ini. Di sisi lain, jika Anda ingin menggunakan hanya tiga pertama Anda akan menggunakan .Take:

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

Ini bahkan dapat dipasangkan bersama, jadi jika Anda hanya menginginkan 4-6 item, Anda dapat melakukan:

foreach (string curString in myCollection.Skip(3).Take(3))
MoarCodePlz
sumber
Panggilan yang bagus. Pelengkapan otomatis WTB (gahh tidak dapat mengingat nama aslinya) di stackoverflow;)
MoarCodePlz
Apakah ini benar-benar melewati atau hanya membuat salinan? IE akan membedakan keduanya: 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

Paling mudah menggunakan Skipmetode di LINQ ke Objek untuk ini, untuk melewati sejumlah elemen:

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

Jelas hanya mengubah 1 untuk nilai lain untuk melewati sejumlah elemen yang berbeda ...

Demikian pula Anda dapat menggunakan Takeuntuk membatasi jumlah elemen yang dikembalikan.

Anda dapat membaca lebih lanjut tentang keduanya (dan yang terkait SkipWhileserta TakeWhilemetode) di seri blog Edulinq saya .

Jon Skeet
sumber
Jon, bukankah ini menjalankan risiko pengecualian jika "urutan" adalah Null?
WEFX
@WEFX: Kami tidak tahu apakah sequencebisa sah nullatau tidak. Agaknya OP dapat mengatasinya sendiri - itu bukan bagian dari pertanyaan ...
Jon Skeet
5

Anda dapat menggunakan Enumerable.Skip untuk melewati beberapa elemen, dan memulainya dari sana.

Sebagai contoh:

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

Namun, jika Anda menulis pohon, Anda mungkin ingin memberikan anggota pada item pohon itu sendiri yang akan mengembalikan baru IEnumerable<T>yang akan dihitung dari sana. Ini secara potensial akan lebih berguna dalam jangka panjang.

Reed Copsey
sumber
Sesuatu seperti IEnumerable<T> SubTree(rootIndex)? Panggilan yang bagus!
Dan J
Terima kasih atas jawabannya, lewati terlihat menjanjikan, membaca informasi MSDN tentang lewati Saya sampai pada kesimpulan bahwa mungkin mungkin untuk menulis metode StartFrom (pohon <MyTree> IEnumerable ini, elemen MyTreeElement) yang akan menjadi metode ekstensi untuk IEnumerable <MyTree> yang mana akan mengembalikan IEnumerable <MyTreeElement> dari mana saya harus memulai iterasi. Maka mungkin saya bisa menggunakan metode ini sebagai foreach (elemen var di tree.StartFrom (someElement))).
neraka
@inferno: Ya, Anda dapat dengan mudah melakukan itu. Namun, saya hanya akan menambahkan metode / properti ke MyTreeElement yang lebih seperti:, IEnumerable<MyTreeElement> Childrenjadi Anda bisa melakukan: foreach(var item in someElement.Children)- jauh lebih jelas daripada menggunakan metode ekstensi IMO.
Reed Copsey
-1

Foreachakan mengulangi koleksi Anda dengan cara yang ditentukan oleh penerapan Anda IEnumerable. Jadi, meskipun Anda bisa melewati elemen (seperti yang disarankan di atas), secara teknis Anda masih mengulang elemen dalam urutan yang sama.

Tidak yakin apa yang ingin Anda capai, tetapi kelas Anda bisa memiliki beberapa IEnumerableproperti, yang masing-masingnya menghitung elemen dalam urutan tertentu.

rampok
sumber
-1

Jika Anda ingin melewatkan membaca Baris dalam a DataGridView, coba ini

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

Jika Anda ingin menyalin konten dari satu DataGridViewbaris ke baris lain yang dilewati, coba ini,

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

ini menyalin konten dari satu DataGridViewke lainnya dengan melewatkan 3 baris.

Juned Khan Momin
sumber
Ini tidak menjawab pertanyaan yang ditanyakan - pertanyaan tidak menyebutkan DataGridViewsama sekali (atau bahkan kerangka UI).
NightOwl888
@ NightOwl888 ini dijawab karena pertanyaannya adalah tentang melewatkan beberapa iterasi dan iterasi setelah itu di foreach loop. Dalam contoh saya, saya hanya menggunakan Skip () untuk diterapkan di DataGridView.
Juned Khan Momin