ตรวจสอบว่ารายการ <t> มีรายการอื่นหรือไม่


97

ฉันมีรายการพารามิเตอร์ดังนี้:

public class parameter
{
    public string name {get; set;}
    public string paramtype {get; set;}
    public string source {get; set;}
}

IEnumerable<Parameter> parameters;

และอาร์เรย์ของสตริงที่ฉันต้องการตรวจสอบ

string[] myStrings = new string[] { "one", "two"};

ฉันต้องการวนซ้ำรายการพารามิเตอร์และตรวจสอบว่าคุณสมบัติต้นทางเท่ากับอาร์เรย์ myStrings หรือไม่ ฉันสามารถทำได้ด้วย foreach ที่ซ้อนกัน แต่ฉันต้องการเรียนรู้วิธีการทำในวิธีที่ดีกว่าเนื่องจากฉันเล่นกับ linq และชอบวิธีการขยายในการแจกแจงเช่นที่อื่น ๆ ดังนั้น foreach ที่ซ้อนกันจึงรู้สึกผิด มีวิธี linq / lambda / delegete ที่หรูหรากว่าในการทำเช่นนี้หรือไม่

ขอบคุณ

คำตอบ:


208

คุณสามารถใช้การAny()ตรวจสอบที่ซ้อนกันสำหรับการตรวจสอบนี้ซึ่งมีอยู่ในEnumerable:

bool hasMatch = myStrings.Any(x => parameters.Any(y => y.source == x));

ได้เร็วขึ้นแสดงบนคอลเลกชันขนาดใหญ่จะเป็นโครงการparametersที่จะsourceแล้วใช้Intersectซึ่งภายในใช้HashSet<T>ดังนั้นแทนที่จะ O (n ^ 2) สำหรับวิธีแรก (เทียบเท่าของสองวงซ้อนกัน) คุณสามารถทำเครื่องหมายใน O (n):

bool hasMatch = parameters.Select(x => x.source)
                          .Intersect(myStrings)
                          .Any(); 

นอกจากนี้ในฐานะความคิดเห็นด้านข้างคุณควรใช้ชื่อชั้นเรียนและชื่อคุณสมบัติของคุณเป็นตัวพิมพ์ใหญ่เพื่อให้สอดคล้องกับหลักเกณฑ์สไตล์ C #


ขอบคุณดูเหมือนจะเป็นสิ่งที่ฉันกำลังมองหาฉันจะลองดู ต้องเล่นกับด้านการทำงานของสิ่งต่างๆอีกเล็กน้อย เกี่ยวกับการใช้ตัวพิมพ์ใหญ่ระดับและคุณสมบัติฉันเพิ่งลืมเมื่อเขียนตัวอย่างด้านบน
gdp

1
ทำไม O (n ^ 2)? ไม่ใช่ O (n * m) ในขณะที่เรากำลังพูดถึงตัวแปรสองตัวไม่ใช่ตัวเดียวใช่หรือไม่? เนื่องจาก m (พารามิเตอร์) เป็นค่าคงที่จึงเหมือนกับ O (n) ฉันไม่เห็นว่าจุดตัดควรเร็วกว่าที่นี่มากแค่ไหน? แต่เห็นด้วย Intersect มีศักยภาพที่จะเร็วกว่า แต่ไม่รับประกัน
Squazz

คุณคิดถูกแล้วที่ควรเป็น O (n * m) - m ไม่ใช่ค่าคงที่ - เป็นขนาดของรายการใดรายการหนึ่งแม้ว่าในตัวอย่างที่ระบุอาจเป็น "2" แม้ค่าคงที่แม้ว่าจะไม่สำคัญในทางปฏิบัติก็ตาม - สำหรับความยาวของรายการที่ไม่สำคัญทั้งหมดความยาวIntersectจะเร็วขึ้น - หากรายการสั้นเล็กน้อยก็ไม่สำคัญว่าทางใดทางหนึ่ง (ในกรณีนั้นประสิทธิภาพอาจไม่ใช่ข้อกังวลของคุณเลย )
BrokenGlass

คุณจะหาดัชนีรายการที่เงื่อนไขเป็นจริงได้อย่างไร ฉันมีรายชื่อพร้อมประโยค ฉันมีอาร์เรย์ที่มีคำเฉพาะ ฉันต้องการดัชนีของรายการหากประโยคนั้นมีอย่างน้อยหนึ่งคำจากอาร์เรย์ @BrokenGlass
kirushan

1
ประสิทธิภาพที่ดีจะไม่parameters.Any(x => myStrings.Contains(x.source));ดีไปกว่าตัวอย่างแรกของคุณหรือ?
Fluppe

3

นี่คือตัวอย่างเพื่อดูว่ามีองค์ประกอบที่ตรงกันในรายการอื่นหรือไม่

List<int> nums1 = new List<int> { 2, 4, 6, 8, 10 };
List<int> nums2 = new List<int> { 1, 3, 6, 9, 12};

if (nums1.Any(x => nums2.Any(y => y == x)))
{
    Console.WriteLine("There are equal elements");
}
else
{
    Console.WriteLine("No Match Found!");
}

2
โปรดทราบว่าหากรายการที่เกี่ยวข้องมีขนาดใหญ่สิ่งนี้จะจบลงช้ากว่าIntersectวิธีการมากเนื่องจากเป็น O (N * M) ในขนาดของรายการ (เป็น O (1) ในความทรงจำ)
Jon Skeet

1

หากทั้งสองรายการใหญ่เกินไปและเมื่อเราใช้นิพจน์ lamda การดึงข้อมูลจะใช้เวลานาน ควรใช้ linq ในกรณีนี้เพื่อดึงรายการพารามิเตอร์:

var items = (from x in parameters
                join y in myStrings on x.Source equals y
                select x)
            .ToList();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.