ฉันมีรายการไบต์เล็ก ๆ และต้องการทดสอบว่าเป็นค่าที่ต่างกันทั้งหมด ตัวอย่างเช่นฉันมีสิ่งนี้:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
วิธีใดที่ดีที่สุดในการตรวจสอบว่าค่าทั้งหมดแตกต่างกันหรือไม่?
ฉันมีรายการไบต์เล็ก ๆ และต้องการทดสอบว่าเป็นค่าที่ต่างกันทั้งหมด ตัวอย่างเช่นฉันมีสิ่งนี้:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
วิธีใดที่ดีที่สุดในการตรวจสอบว่าค่าทั้งหมดแตกต่างกันหรือไม่?
คำตอบ:
bool isUnique = theList.Distinct().Count() == theList.Count();
นี่เป็นอีกแนวทางหนึ่งที่มีประสิทธิภาพมากกว่าEnumerable.Distinct+ Enumerable.Count(ยิ่งถ้าลำดับไม่ใช่ประเภทคอลเลกชัน) ใช้HashSet<T>ซึ่งกำจัดรายการที่ซ้ำกันมีประสิทธิภาพมากในการค้นหาและมีคุณสมบัติการนับ:
var distinctBytes = new HashSet<byte>(theList);
bool allDifferent = distinctBytes.Count == theList.Count;
หรือวิธีอื่นที่ละเอียดกว่าและมีประสิทธิภาพ:
var diffChecker = new HashSet<byte>();
bool allDifferent = theList.All(diffChecker.Add);
HashSet<T>.Addส่งคืนfalseหากไม่สามารถเพิ่มองค์ประกอบได้เนื่องจากมีอยู่แล้วในไฟล์HashSet. Enumerable.Allหยุดที่ "เท็จ" ตัวแรก
Assert.IsTrue(samples.Add(AwesomeClass.GetUnique()));ล้านองค์ประกอบที่สร้างโดยรหัสที่น่ากลัวของฉันจะไม่ซ้ำกันจริงๆ พวกเขาเป็นและเป็น :) +1 สำหรับคุณ Tim :)
bool allDifferent = theList.All(s => diffChecker.Add(s))
List.All(HashSet.Add)) ดูเหมือนจะเร็วกว่าอีกสองอย่างในเกือบทุกกรณี
โอเคนี่เป็นวิธีที่มีประสิทธิภาพที่สุดที่ฉันคิดได้จากการใช้. Net มาตรฐาน
using System;
using System.Collections.Generic;
public static class Extension
{
public static bool HasDuplicate<T>(
this IEnumerable<T> source,
out T firstDuplicate)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var checkBuffer = new HashSet<T>();
foreach (var t in source)
{
if (checkBuffer.Add(t))
{
continue;
}
firstDuplicate = t;
return true;
}
firstDuplicate = default(T);
return false;
}
}
โดยพื้นฐานแล้วอะไรคือจุดในการแจกแจงลำดับทั้งหมดสองครั้งหากสิ่งที่คุณต้องการทำคือค้นหารายการแรกที่ซ้ำกัน
ฉันสามารถปรับสิ่งนี้ให้เหมาะสมได้มากขึ้นโดยการจัดเรียงลำดับองค์ประกอบว่างเปล่าและองค์ประกอบเดี่ยวแบบพิเศษ แต่จะลดลงจากความสามารถในการอ่าน / การบำรุงรักษาโดยได้รับน้อยที่สุด
sequenceควรจะเป็นsource) แต่ใช้งานได้ดีเมื่อได้รับการแก้ไขแล้ว
if (!checkBuffer.Add(t)) { firstDuplicate = t; return true }อยู่ในวง
ตรรกะที่คล้ายกันในการDistinctใช้GroupBy:
var isUnique = theList.GroupBy(i => i).Count() == theList.Count;
theList.GroupBy(o => o.SomeProperty).Count() == theList.Count;ในขณะที่ Distinct () ไม่อนุญาต
นอกจากนี้ยังสามารถทำได้: ใช้แฮชเซ็ต
var uniqueIds = new HashSet<long>(originalList.Select(item => item.Id));
if (uniqueIds.Count != originalList.Count)
{
}
มีวิธีแก้มากมาย
และไม่ต้องสงสัยเลยว่าสวยขึ้นด้วยการใช้ LINQ ตามที่ "juergen d" และ "Tim Schmelter" กล่าวไว้
แต่ถ้าคุณเปิดเผย "ความซับซ้อน" และความเร็วทางออกที่ดีที่สุดคือการนำไปใช้ด้วยตัวเอง หนึ่งในวิธีแก้ปัญหาคือการสร้างอาร์เรย์ขนาด N (สำหรับไบต์คือ 256) และวนรอบอาร์เรย์และในการวนซ้ำทุกครั้งจะทดสอบดัชนีตัวเลขที่ตรงกันว่าค่าเป็น 1 ถ้าเป็นเช่นนั้นหมายความว่าฉันเพิ่มดัชนีอาร์เรย์แล้วดังนั้นอาร์เรย์จึงไม่แตกต่างกันมิฉะนั้นฉันจะเพิ่มเซลล์อาร์เรย์และทำการตรวจสอบต่อไป .
และอีกวิธีหนึ่งหากคุณต้องการค้นหาค่าที่ซ้ำกัน
var values = new [] { 9, 7, 2, 6, 7, 3, 8, 2 };
var sorted = values.ToList();
sorted.Sort();
for (var index = 1; index < sorted.Count; index++)
{
var previous = sorted[index - 1];
var current = sorted[index];
if (current == previous)
Console.WriteLine(string.Format("duplicated value: {0}", current));
}
เอาท์พุต:
duplicated value: 2
duplicated value: 7
ฉันตรวจสอบว่า IEnumerable (aray, list, ฯลฯ ) ไม่ซ้ำกันเช่นนี้:
var isUnique = someObjectsEnum.GroupBy(o => o.SomeProperty).Max(g => g.Count()) == 1;