รายการสตริงเฉพาะ C # ที่มีประสิทธิภาพ


86

วิธีใดที่มีประสิทธิภาพที่สุดในการจัดเก็บรายการสตริงโดยไม่สนใจรายการที่ซ้ำกัน ฉันคิดว่าพจนานุกรมอาจจะแทรกสตริงได้ดีที่สุดโดยการเขียน dict [str] = false; และแจกแจงผ่านคีย์เป็นรายการ นั่นเป็นทางออกที่ดีหรือไม่?

คำตอบ:


111

หากคุณใช้. NET 3.5 HashSet น่าจะเหมาะกับคุณ

คลาส HashSet <(Of <(T>)>) ให้การดำเนินการเซ็ตประสิทธิภาพสูง ชุดคือคอลเล็กชันที่ไม่มีองค์ประกอบที่ซ้ำกันและองค์ประกอบที่ไม่เรียงลำดับกัน


6
แต่HashSetจะสูญเสียลำดับของรายการ คุณลักษณะที่Listให้
aggsol

5
เพิ่มเติม: นอกจากนี้ยังมี SortedSet <T> ซึ่งเป็น HashSet ที่จัดเรียงได้สะดวก
WhoIsRich

นอกจากนี้โปรดทราบว่าไม่สามารถเข้าถึง HashSet ผ่านดัชนีได้ต้องใช้ตัวแจงนับที่ตรงข้ามกับ List เท่านั้น
Andrew

23

คุณสามารถทำสิ่งนี้ได้

var hash = new HashSet<string>();
var collectionWithDup = new []{"one","one","two","one","two","zero"}; 

// No need to check for duplicates as the Add method
// will only add it if it doesn't exist already
foreach (var str in collectionWithDup)
    hash.Add(str);   

33
คุณไม่จำเป็นต้องมีการตรวจสอบกับ HashSet คุณสามารถเรียกใช้เมธอด Add ได้โดยตรงและจะส่งคืนจริงหรือเท็จขึ้นอยู่กับว่ามีรายการนั้นอยู่แล้วหรือไม่
LukeH

1
คำตอบควรได้รับการแก้ไขเพื่อลบการเรียกไปยังมีที่ซ้ำซ้อน สิ่งที่คุณต้องการเพื่อให้ตัวอย่างข้างต้นใช้งานได้: var collectionWithDup = new [] {"one", "one", "two", "one", "two", "zero"}; var uniqueValues ​​= HashSet ใหม่ <string> (collectionWithDup);
user3285954

14

ฉันไม่แน่ใจว่านี่เป็นคำตอบที่ดีหรือไม่ แต่เมื่อต้องเผชิญกับความต้องการชุดที่ไม่เหมือนใครที่รักษาลำดับการแทรกฉันก็ยอมแพ้กับ HashSet และ List เคียงข้างกัน ในกรณีนี้เมื่อใดก็ตามที่คุณเพิ่มลงในชุดให้ทำดังต่อไปนี้:

if(hashSet.Add(item))
    orderList.Add(item);

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


10

คุณยังสามารถใช้ Linq ได้ใน:

using System.Linq;

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };

List<string> distinctItems = items.Distinct().ToList();

8

ใช้ HashSet ไม่จำเป็นต้องตรวจสอบContains () เพียงแค่เพิ่มรายการของคุณในรายการและหากซ้ำกันก็จะไม่เพิ่มเข้าไป

   HashSet<int> uniqueList = new HashSet<int>();
   uniqueList.Add(1); // List has values 1
   uniqueList.Add(2);  // List has values 1,2
   uniqueList.Add(1);  // List has values 1,2
   Console.WriteLine(uniqueList.Count); // it will return 2

2

นี่ไม่ใช่ส่วนหนึ่งของเนมสเปซระบบ แต่ใช้ Iesi.Collections จากhttp://www.codeproject.com/KB/recipes/sets.aspxกับ NHibernate มีการสนับสนุนชุดแฮชพร้อมกับชุดที่เรียงชุดพจนานุกรมและอื่น ๆ เนื่องจากมีการใช้กับ NHibernate จึงมีการใช้งานอย่างกว้างขวางและมีเสถียรภาพมาก นอกจากนี้ยังไม่ต้องใช้. Net 3.5


2

นี่เป็นอีกวิธีหนึ่งโดยไม่ต้องใช้ไฟล์HashSet.

var items = new List<string>() { "one", "one", "two", "one", "two", "zero" };
var uniqueItems = items.Where((item, index) => items.IndexOf(item) == index);

มันถูกนำมาใช้จากเธรดนี้: javascript - ค่าที่ไม่ซ้ำกันในอาร์เรย์

ทดสอบ:

using FluentAssertions;

uniqueItems.Count().Should().Be(3);
uniqueItems.Should().BeEquivalentTo("one", "two", "zero");

การทดสอบประสิทธิภาพการทำงานสำหรับList, และHashSet SortedSet1 ล้านซ้ำ:

List: 564 ms
HashSet: 487 ms
SortedSet: 1932 ms

ทดสอบซอร์สโค้ด (ส่วนสำคัญ)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.