ฉันใช้ LINQ กับคำสั่ง Objects ในอาเรย์ที่สั่ง การดำเนินการใดที่ฉันไม่ควรทำเพื่อให้แน่ใจว่าลำดับของอาร์เรย์จะไม่เปลี่ยนแปลง?
ฉันใช้ LINQ กับคำสั่ง Objects ในอาเรย์ที่สั่ง การดำเนินการใดที่ฉันไม่ควรทำเพื่อให้แน่ใจว่าลำดับของอาร์เรย์จะไม่เปลี่ยนแปลง?
คำตอบ:
ฉันตรวจสอบวิธีการของSystem.Linq.Enumerableยกเลิกสิ่งที่ส่งคืนผลลัพธ์ที่ไม่ใช่ IEnumerable ฉันตรวจสอบคำพูดของแต่ละคนเพื่อพิจารณาว่าลำดับของผลลัพธ์จะแตกต่างจากลำดับของแหล่งที่มาอย่างไร
รักษาคำสั่งซื้ออย่างแน่นอน คุณสามารถแมปองค์ประกอบที่มาด้วยดัชนีไปยังองค์ประกอบผลลัพธ์
รักษาคำสั่งซื้อ องค์ประกอบถูกกรองหรือเพิ่ม แต่ไม่ได้สั่งใหม่
ทำลายคำสั่งซื้อ - เราไม่ทราบว่าจะสั่งซื้อผลลัพธ์ใด
กำหนดคำสั่งใหม่อย่างชัดเจน - ใช้สิ่งเหล่านี้เพื่อเปลี่ยนลำดับของผลลัพธ์
กำหนดคำสั่งใหม่ตามกฎบางอย่าง
แก้ไข: ฉันย้ายส่วนที่แตกต่างไปยังการเก็บรักษาใบสั่งตามการใช้งานนี้
private static IEnumerable<TSource> DistinctIterator<TSource>
(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
Distinct
วิธีการ) อาจหมายถึงการพูดว่า "ไม่ได้เรียงลำดับ" ไม่ใช่ "ตามลำดับที่คาดเดาไม่ได้" ผมว่าเป็นของประเภทการกรองข้างต้นเช่นเดียวกับDistinct
Where
คุณกำลังพูดถึง SQL จริง ๆ หรือเกี่ยวกับอาร์เรย์ หากต้องการใช้อีกวิธีหนึ่งคุณใช้ LINQ กับ SQL หรือ LINQ กับวัตถุหรือไม่
ตัวดำเนินการ LINQ เป็นวัตถุไม่ได้เปลี่ยนแหล่งข้อมูลดั้งเดิมของพวกเขา - พวกเขาสร้างลำดับที่สำรองข้อมูลได้อย่างมีประสิทธิภาพโดยแหล่งข้อมูล การดำเนินการเดียวที่เปลี่ยนการสั่งซื้อคือ OrderBy / OrderByDescending / ThenBy / ThenByDescending - และแม้กระทั่งนั้นจะมีเสถียรภาพสำหรับองค์ประกอบที่สั่งซื้อเท่ากัน แน่นอนการดำเนินการจำนวนมากจะกรององค์ประกอบบางอย่าง แต่องค์ประกอบที่ส่งคืนจะอยู่ในลำดับเดียวกัน
หากคุณแปลงเป็นโครงสร้างข้อมูลที่แตกต่างกันเช่นด้วย ToLookup หรือ ToDictionary ฉันไม่เชื่อว่าคำสั่งซื้อจะได้รับการเก็บรักษาไว้ ณ จุดนั้น - แต่นั่นก็ค่อนข้างแตกต่างกันอยู่ดี (ลำดับของการจับคู่ค่ากับคีย์เดียวกันนั้นสงวนไว้สำหรับการค้นหาแม้ว่าฉันเชื่อ)
GroupBy
ตามด้วยSelectMany
จะให้ผลลัพธ์ที่จัดกลุ่มตามคีย์ แต่ไม่เรียงลำดับคีย์ ... จะให้เรียงตามลำดับที่คีย์เกิดขึ้น
list<x> {a b c d e f g}
ถ้า c, d, e ทั้งหมดมีคีย์เดียวกันดังนั้นลำดับที่ได้จะมี c, d, e ติดกันและในลำดับ c, d, e ฉันไม่สามารถหาคำตอบจาก MS อย่างเด็ดขาด
หากคุณกำลังทำงานกับอาเรย์ดูเหมือนว่าคุณกำลังใช้ LINQ-to-Objects ไม่ใช่ SQL; คุณยืนยันได้ไหม การทำงานของ LINQ ส่วนใหญ่จะไม่เรียงลำดับอะไรใหม่ (ผลลัพธ์จะอยู่ในลำดับเดียวกันกับอินพุต) - ดังนั้นอย่าใช้การเรียงลำดับอื่น (OrderB โดย [Descending] / จากนั้นโดย [Descending])
[แก้ไข: ตามที่จอนระบุไว้ชัดเจนยิ่งขึ้น; โดยทั่วไป LINQ จะสร้างลำดับใหม่โดยปล่อยให้ข้อมูลต้นฉบับอยู่คนเดียว
โปรดทราบว่าการกดข้อมูลลงในDictionary<,>
(ToDictionary) จะแย่งข้อมูลเนื่องจากพจนานุกรมไม่เคารพลำดับการเรียงลำดับใด ๆ
แต่สิ่งที่พบบ่อยที่สุด (เลือก, ที่ไหน, ข้าม, รับ) ควรจะใช้ได้
ToDictionary()
เพียงแค่ไม่ได้สัญญาเกี่ยวกับคำสั่งซื้อ แต่ในทางปฏิบัติจะรักษาลำดับการป้อนข้อมูลไว้ (จนกว่าคุณจะลบบางสิ่งออกจากมัน) ฉันไม่ได้บอกว่าจะพึ่งพาสิ่งนี้ แต่ 'การแย่งชิง' ดูเหมือนจะไม่ถูกต้อง
ฉันพบคำตอบที่ดีในคำถามที่คล้ายกันซึ่งอ้างอิงเอกสารอย่างเป็นทางการ อ้างถึง:
สำหรับEnumerable
วิธีการ (LINQ กับวัตถุที่ใช้กับList<T>
) คุณสามารถพึ่งพาลำดับขององค์ประกอบที่ส่งกลับโดยSelect
, หรือWhere
GroupBy
กรณีนี้ไม่ได้สำหรับสิ่งที่ไม่เรียงลำดับโดยเนื้อแท้เหมือนหรือToDictionary
Distinct
จากเอกสารEnumerable.GroupBy :
วัตถุที่มีการให้ผลในลำดับที่ตามลำดับขององค์ประกอบในแหล่งที่ผลิตกุญแจดอกแรกของแต่ละคน
IGrouping<TKey, TElement>
องค์ประกอบในการจัดกลุ่มจะให้ผลตามลำดับที่ปรากฏในIGrouping<TKey, TElement>
source
สิ่งนี้ไม่เป็นความจริงสำหรับIQueryable
วิธีการขยาย (ผู้ให้บริการ LINQ อื่น ๆ )
แหล่งที่มา: วิธีที่นับได้ของ LINQ สามารถรักษาลำดับองค์ประกอบที่สัมพันธ์กันได้หรือไม่?
'จัดกลุ่มตาม' หรือ 'สั่งซื้อโดย' อาจมีการเปลี่ยนแปลงคำสั่งซื้อ
คำถามที่นี่อ้างถึง LINQ-to-Objects โดยเฉพาะ
หากคุณใช้ LINQ-to-SQL แทนจะไม่มีคำสั่งซื้อที่นั่นเว้นแต่คุณจะกำหนดสิ่งที่ต้องการ:
mysqlresult.OrderBy(e=>e.SomeColumn)
หากคุณไม่ทำเช่นนี้กับ LINQ-to-SQL ลำดับของผลลัพธ์อาจแตกต่างกันระหว่างคิวรีที่ตามมาแม้ในข้อมูลเดียวกันซึ่งอาจทำให้เกิดบั๊กที่ไม่สม่ำเสมอ