[c#] सूची <T> से तत्वों को निकालने के लिए LINQ का उपयोग करना


Answers

RemoveAll का उपयोग करना बेहतर होगा। इसे पूरा करने के लिए सभी को RemoveAll

authorsList.RemoveAll((x) => x.firstname == "Bob");
Question

कहें कि मेरे पास LINQ क्वेरी है जैसे कि:

var authors = from x in authorsList
              where x.firstname == "Bob"
              select x;

यह देखते हुए कि authorsList की List<Author> , मैं Author authors के Author तत्वों को कैसे हटा सकता हूं जो क्वेरी में authors द्वारा लौटाए गए हैं?

या, एक और तरीका डालें, मैं authorsList से authorsList नाम के बराबर बॉब को कैसे हटा सकता हूं?

नोट: यह प्रश्न के प्रयोजनों के लिए एक सरलीकृत उदाहरण है।




आप मानक LINQ ऑपरेटरों के साथ ऐसा नहीं कर सकते क्योंकि LINQ क्वेरी प्रदान करता है, समर्थन अपडेट नहीं करता है।

लेकिन आप एक नई सूची उत्पन्न कर सकते हैं और पुराने को प्रतिस्थापित कर सकते हैं।

var authorsList = GetAuthorList();

authorsList = authorsList.Where(a => a.FirstName != "Bob").ToList();

या आप दूसरे पास में authors में सभी वस्तुओं को हटा सकते हैं।

var authorsList = GetAuthorList();

var authors = authorsList.Where(a => a.FirstName == "Bob").ToList();

foreach (var author in authors)
{
    authorList.Remove(author);
}



आप दो तरीकों से हटा सकते हैं

var output = from x in authorsList
             where x.firstname != "Bob"
             select x;

या

var authors = from x in authorsList
              where x.firstname == "Bob"
              select x;

var output = from x in authorsList
             where !authors.Contains(x) 
             select x;

मुझे एक ही समस्या थी, अगर आप अपनी स्थिति के आधार पर सरल आउटपुट चाहते हैं, तो पहला समाधान बेहतर है।




LINQ की उत्पत्ति प्रोग्रामिंग प्रोग्रामिंग में है, जो ऑब्जेक्ट्स की अपरिवर्तनीयता पर जोर देती है, इसलिए यह मूल सूची को जगह में अपडेट करने का एक अंतर्निहित तरीका प्रदान नहीं करता है।

अपरिवर्तनीयता पर ध्यान दें (किसी अन्य SO उत्तर से लिया गया):

विकिपीडिया (लिंक) से अपरिवर्तनीयता की परिभाषा यहां दी गई है

"ऑब्जेक्ट उन्मुख और कार्यात्मक प्रोग्रामिंग में, एक अपरिवर्तनीय वस्तु एक वस्तु है जिसका निर्माण इसे बनाने के बाद संशोधित नहीं किया जा सकता है।"




मुझे लगता है कि आप ऐसा कुछ कर सकते हैं

    authorsList = (from a in authorsList
                  where !authors.Contains(a)
                  select a).ToList();

हालांकि मुझे लगता है कि पहले से दिए गए समाधानों को समस्या को और अधिक पठनीय तरीके से हल किया गया है।




बहुत आसान है:

authorsList.RemoveAll((x) => x.firstname == "Bob");



मैं घूम रहा था, अगर हैशसेट के अलावा निकालें और छोड़कर और पेशेवरों के बीच कोई अंतर है, तो मैंने त्वरित प्रदर्शन जांच की है :)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace ListRemoveTest
{
    class Program
    {
        private static Random random = new Random( (int)DateTime.Now.Ticks );

        static void Main( string[] args )
        {
            Console.WriteLine( "Be patient, generating data..." );

            List<string> list = new List<string>();
            List<string> toRemove = new List<string>();
            for( int x=0; x < 1000000; x++ )
            {
                string randString = RandomString( random.Next( 100 ) );
                list.Add( randString );
                if( random.Next( 1000 ) == 0 )
                    toRemove.Insert( 0, randString );
            }

            List<string> l1 = new List<string>( list );
            List<string> l2 = new List<string>( list );
            List<string> l3 = new List<string>( list );
            List<string> l4 = new List<string>( list );

            Console.WriteLine( "Be patient, testing..." );

            Stopwatch sw1 = Stopwatch.StartNew();
            l1.RemoveAll( toRemove.Contains );
            sw1.Stop();

            Stopwatch sw2 = Stopwatch.StartNew();
            l2.RemoveAll( new HashSet<string>( toRemove ).Contains );
            sw2.Stop();

            Stopwatch sw3 = Stopwatch.StartNew();
            l3 = l3.Except( toRemove ).ToList();
            sw3.Stop();

            Stopwatch sw4 = Stopwatch.StartNew();
            l4 = l4.Except( new HashSet<string>( toRemove ) ).ToList();
            sw3.Stop();


            Console.WriteLine( "L1.Len = {0}, Time taken: {1}ms", l1.Count, sw1.Elapsed.TotalMilliseconds );
            Console.WriteLine( "L2.Len = {0}, Time taken: {1}ms", l1.Count, sw2.Elapsed.TotalMilliseconds );
            Console.WriteLine( "L3.Len = {0}, Time taken: {1}ms", l1.Count, sw3.Elapsed.TotalMilliseconds );
            Console.WriteLine( "L4.Len = {0}, Time taken: {1}ms", l1.Count, sw3.Elapsed.TotalMilliseconds );

            Console.ReadKey();
        }


        private static string RandomString( int size )
        {
            StringBuilder builder = new StringBuilder();
            char ch;
            for( int i = 0; i < size; i++ )
            {
                ch = Convert.ToChar( Convert.ToInt32( Math.Floor( 26 * random.NextDouble() + 65 ) ) );
                builder.Append( ch );
            }

            return builder.ToString();
        }
    }
}

नीचे परिणाम:

Be patient, generating data...
Be patient, testing...
L1.Len = 985263, Time taken: 13411.8648ms
L2.Len = 985263, Time taken: 76.4042ms
L3.Len = 985263, Time taken: 340.6933ms
L4.Len = 985263, Time taken: 340.6933ms

जैसा कि हम देख सकते हैं, उस मामले में सबसे अच्छा विकल्प RemoveAll (हैशसेट) का उपयोग करना है




Related