เป็นไปได้ไหมที่จะเริ่มทำซ้ำจากองค์ประกอบอื่นที่ไม่ใช่องค์ประกอบแรกโดยใช้ foreach


89

ฉันกำลังคิดที่จะใช้ IEnumerable สำหรับคอลเลกชันที่กำหนดเองของฉัน (ต้นไม้) ดังนั้นฉันจึงสามารถใช้ foreach เพื่อสำรวจต้นไม้ของฉันได้ อย่างไรก็ตามเท่าที่ฉันรู้ foreach มักจะเริ่มจากองค์ประกอบแรกของคอลเลกชัน ฉันต้องการเลือกจากองค์ประกอบที่ foreach เริ่มต้น เป็นไปได้ไหมที่จะเปลี่ยนองค์ประกอบที่ foreach เริ่มต้น?


1
ฉันจะปฏิบัติตามหลักการของความประหลาดใจอย่างน้อยที่สุด: en.wikipedia.org/wiki/Principle_of_least_astonishment
ChaosPandion

หากคุณไม่เริ่มจากองค์ประกอบแรกคุณจะกำหนดพฤติกรรมของตัววนซ้ำได้อย่างไร จะเกิดอะไรขึ้นเมื่อถึงจุดสิ้นสุดของลำดับ จากนั้นกลับไปที่องค์ประกอบแรกและวนซ้ำองค์ประกอบที่เหลืออยู่หรือไม่?
Dan J

ความคิดเห็นของ @ ChaosPandion คือที่ที่ฉันจะไปกับคำถามเหล่านั้น :)
Dan J

คำตอบ:


165

ใช่. ดำเนินการดังต่อไปนี้:

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

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

Skipเป็นฟังก์ชันที่สามารถคำนวณได้ของ IE ซึ่งข้ามจำนวนที่คุณระบุโดยเริ่มจากดัชนีปัจจุบัน ในทางกลับกันหากคุณต้องการใช้เพียงสามอย่างแรกคุณจะใช้.Take:

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

สิ่งเหล่านี้สามารถจับคู่กันได้ดังนั้นหากคุณต้องการเพียง 4-6 รายการคุณสามารถทำได้:

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

โทร. การทำให้สมบูรณ์อัตโนมัติ WTB (gahh จำชื่อจริงไม่ได้) ใน stackoverflow;)
MoarCodePlz

สิ่งนี้ข้ามไปจริงๆหรือแค่สร้างสำเนา? IE จะทั้งสองจะแตกต่างกัน: 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

ง่ายที่สุดในการใช้Skipวิธีการใน LINQ ถึง Objects เพื่อข้ามองค์ประกอบที่กำหนด:

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

เห็นได้ชัดว่าเพียงแค่เปลี่ยน 1 สำหรับค่าอื่น ๆ เพื่อข้ามองค์ประกอบต่างๆ ...

ในทำนองเดียวกันคุณสามารถใช้Takeเพื่อ จำกัด จำนวนองค์ประกอบที่จะส่งคืน

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับทั้งสองคนนี้ (และที่เกี่ยวข้องSkipWhileและTakeWhileวิธีการ) ในชุดบล็อก Edulinq ของฉัน


จอนนี่จะไม่เสี่ยงต่อการเกิดข้อยกเว้นหรือไม่ถ้า "ลำดับ" เป็น Null
WEFX

@WEFX: เราไม่รู้ว่าsequenceจะถูกต้องตามกฎหมายnullหรือไม่ สันนิษฐานว่า OP สามารถจัดการได้เอง - ไม่ใช่ส่วนหนึ่งของคำถามจริงๆ ...
Jon Skeet

5

คุณสามารถใช้Enumerableข้ามเพื่อข้ามองค์ประกอบบางส่วนและเริ่มต้นที่นั่น

ตัวอย่างเช่น:

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

อย่างไรก็ตามหากคุณกำลังเขียนต้นไม้คุณอาจต้องการให้สมาชิกในรายการต้นไม้นั้นเองซึ่งจะส่งคืนสินค้าใหม่IEnumerable<T>ซึ่งจะแจกแจงจากที่นั่น สิ่งนี้อาจมีประโยชน์มากกว่าในระยะยาว


บางอย่างเช่นIEnumerable<T> SubTree(rootIndex)? โทรดี!
Dan J

ขอบคุณสำหรับคำตอบข้ามดูมีแนวโน้มอ่านข้อมูล MSDN เกี่ยวกับการข้ามฉันได้ข้อสรุปว่าอาจเป็นไปได้ที่จะเขียนวิธี StartFrom (ต้นไม้ <MyTree> ของ IEnumerable องค์ประกอบ MyTreeElement) ซึ่งจะเป็นวิธีการขยายสำหรับ IEnumerable <MyTree> ซึ่ง จะคืนค่า IEnumerable <MyTreeElement> ซึ่งฉันควรเริ่มทำซ้ำ จากนั้นฉันอาจใช้วิธีนี้เป็น foreach (องค์ประกอบ var ใน tree.StartFrom (someElement)))
inferno

@inferno: ใช่คุณสามารถทำได้อย่างง่ายดาย อย่างไรก็ตามฉันจะเพิ่มวิธีการ / คุณสมบัติให้กับ MyTreeElement ที่ชอบมากขึ้นIEnumerable<MyTreeElement> Childrenดังนั้นคุณสามารถทำได้: foreach(var item in someElement.Children)- ชัดเจนกว่าการใช้วิธีการขยาย IMO
Reed Copsey

-1

Foreachจะวนซ้ำคอลเลกชันของคุณตามวิธีที่กำหนดโดยการนำไปใช้ของIEnumerableคุณ ดังนั้นแม้ว่าคุณจะสามารถข้ามองค์ประกอบได้ (ตามที่แนะนำข้างต้น) แต่ในทางเทคนิคคุณก็ยังคงวนซ้ำองค์ประกอบตามลำดับ

ไม่แน่ใจว่าคุณกำลังพยายามทำอะไรอยู่ แต่ชั้นเรียนของคุณอาจมีIEnumerableคุณสมบัติหลายอย่างซึ่งแต่ละคุณสมบัติจะแจกแจงองค์ประกอบตามลำดับที่เจาะจง


-1

หากคุณต้องการข้ามการอ่านแถวใน a DataGridViewให้ลองทำเช่นนี้

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

หากคุณต้องการคัดลอกเนื้อหาจากDataGridViewแถวหนึ่งไปยังอีกแถวที่ข้ามไปมาให้ลองทำเช่นนี้

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

ซึ่งจะคัดลอกเนื้อหาจากที่หนึ่งDataGridViewไปยังอีกที่หนึ่งโดยข้าม 3 แถว


สิ่งนี้ไม่ตอบคำถามที่ถาม - คำถามไม่ได้กล่าวถึงDataGridViewเลย (หรือแม้แต่กรอบ UI)
NightOwl888

@ NightOwl888 ได้รับคำตอบเนื่องจากคำถามเกี่ยวกับการข้ามการทำซ้ำบางส่วนและทำซ้ำหลังจากนั้นใน foreach loop ในตัวอย่างของฉันฉันเพิ่งใช้ Skip () เพื่อใช้กับ DataGridView
Juned Khan Momin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.