سؤال

أنا أبحث عن طريقة سريعة جدا في أن تنزل مجموعة في C#.أنا حاليا باستخدام عامة قائمة<object> مجموعات, ولكن أنا فتح باستخدام هياكل أخرى إذا كانت أداء أفضل.

حاليا, أنا فقط إنشاء قائمة جديدة<object> وحلقات من خلال القائمة الأصلية.إذا كانت معايير التصفية المباريات, لقد وضعت نسخة في القائمة الجديدة.

هل هناك طريقة أفضل للقيام بذلك ؟ هل هناك طريقة لتصفية في مكان حيث لا يوجد المؤقتة القائمة المطلوبة ؟

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم C# 3.0 يمكنك استخدام linq, طريقة أفضل طريقة أكثر أناقة:

List<int> myList = GetListOfIntsFromSomewhere();

// This will filter out the list of ints that are > than 7, Where returns an
// IEnumerable<T> so a call to ToList is required to convert back to a List<T>.
List<int> filteredList = myList.Where( x => x > 7).ToList();

إذا كنت لا يمكن العثور على .Where, هذا يعني أنك بحاجة إلى استيراد using System.Linq; في الجزء العلوي من الملف الخاص بك.

نصائح أخرى

هنا هو رمز كتلة / مثال على بعض في تصفية قائمة باستخدام ثلاث طرق مختلفة أن أضع معا لإظهار Lambdas و ينق على أساس قائمة الترشيح.

#region List Filtering

static void Main(string[] args)
{
    ListFiltering();
    Console.ReadLine();
}

private static void ListFiltering()
{
    var PersonList = new List<Person>();

    PersonList.Add(new Person() { Age = 23, Name = "Jon", Gender = "M" }); //Non-Constructor Object Property Initialization
    PersonList.Add(new Person() { Age = 24, Name = "Jack", Gender = "M" });
    PersonList.Add(new Person() { Age = 29, Name = "Billy", Gender = "M" });

    PersonList.Add(new Person() { Age = 33, Name = "Bob", Gender = "M" });
    PersonList.Add(new Person() { Age = 45, Name = "Frank", Gender = "M" });

    PersonList.Add(new Person() { Age = 24, Name = "Anna", Gender = "F" });
    PersonList.Add(new Person() { Age = 29, Name = "Sue", Gender = "F" });
    PersonList.Add(new Person() { Age = 35, Name = "Sally", Gender = "F" });
    PersonList.Add(new Person() { Age = 36, Name = "Jane", Gender = "F" });
    PersonList.Add(new Person() { Age = 42, Name = "Jill", Gender = "F" });

    //Logic: Show me all males that are less than 30 years old.

    Console.WriteLine("");
    //Iterative Method
    Console.WriteLine("List Filter Normal Way:");
    foreach (var p in PersonList)
        if (p.Gender == "M" && p.Age < 30)
            Console.WriteLine(p.Name + " is " + p.Age);

    Console.WriteLine("");
    //Lambda Filter Method
    Console.WriteLine("List Filter Lambda Way");
    foreach (var p in PersonList.Where(p => (p.Gender == "M" && p.Age < 30))) //.Where is an extension method
        Console.WriteLine(p.Name + " is " + p.Age);

    Console.WriteLine("");
    //LINQ Query Method
    Console.WriteLine("List Filter LINQ Way:");
    foreach (var v in from p in PersonList
                      where p.Gender == "M" && p.Age < 30
                      select new { p.Name, p.Age })
        Console.WriteLine(v.Name + " is " + v.Age);
}

private class Person
{
    public Person() { }
    public int Age { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
}

#endregion

قائمة FindAll الطريقة التي سيتم القيام تصفية لك عودة مجموعة فرعية من القائمة.

Msdn كبيرة المثال التعليمات البرمجية هنا: http://msdn.microsoft.com/en-us/library/aa701359(مقابل.80).aspx

تحرير:كتبت هذا قبل كان فهم جيد Linq و حيث الأسلوب ().إذا كان لي أن أكتب هذا اليوم ربما أود أن استخدام الأسلوب خورخي ذكر أعلاه.الأسلوب FindAll لا يزال يعمل إذا كنت عالقا في .NET 2.0 البيئة على الرغم من.

يمكنك استخدام IEnumerable للقضاء على الحاجة temp القائمة.

public IEnumerable<T> GetFilteredItems(IEnumerable<T> collection)
{
    foreach (T item in collection)
    if (Matches<T>(item))
    {
        yield return item;
    }
}

حيث يطابق هو اسم عامل التصفية الخاص بك طريقة.و يمكنك استخدام هذا مثل:

IEnumerable<MyType> filteredItems = GetFilteredItems(myList);
foreach (MyType item in filteredItems)
{
    // do sth with your filtered items
}

هذا سوف ندعو GetFilteredItems وظيفة عند الحاجة وفي بعض الحالات التي لا تستخدمها جميع العناصر في تصفية مجموعة ، قد توفر بعض الأداء الجيد مكسب.

يمكنك استخدام FindAll طريقة القائمة ، توفير مندوب مرشح.على الرغم من أنني أتفق مع @IainMH أن الأمر لا يستحق كل هذا القلق نفسك كثيرا إلا إذا كانت قائمة ضخمة.

أن تفعل ذلك في مكان ، يمكنك استخدام RemoveAll طريقة "قائمة<>" الطبقة جنبا إلى جنب مع العرف "المسند" الدرجة...ولكن كل ذلك لا يتم تنظيف رمز...تحت غطاء محرك السيارة انها تفعل نفس الشيء أنت...ولكن نعم ، فإنه يفعل ذلك في مكان ، حتى تفعل نفس temp القائمة.

باستخدام Linq نسبيا الهريسة أبطأ من استخدام المسند الموردة إلى قوائم FindAll الأسلوب.أيضا عليك أن تكون حذرا مع Linq كما eumeration القائمة ليست في الواقع المنفذة حتى يتم الوصول إلى نتيجة.وهذا يمكن أن يعني أنه عندما كنت تعتقد أنك قد خلقت قائمة تم تصفيتها المحتوى قد تختلف إلى ما كنت متوقع عند قراءة الواقع.

إذا كنت تستخدم C# 3.0 يمكنك استخدام linq

أو إذا كنت تفضل استخدام بناء جملة الاستعلام الخاصة التي تقدمها C# 3 مترجم:

var filteredList = from x in myList
                   where x > 7
                   select x;

إذا كان لديك قائمة كبيرة جدا و هي تصفية مرارا وتكرارا - يمكنك فرز القائمة الأصلية على مرشح السمة الثنائية البحث للعثور على نقاط البداية والنهاية.

المرة الأولي O(n*log(n)) ثم O(log(n)).

معيار التصفية سوف تأخذ O(n) في كل مرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top