LINQ: एक वस्तु का चयन करें और एक नई वस्तु बनाए बिना कुछ गुणों को बदलें


218

मैं एक नई वस्तु बनाने और हर संपत्ति को मैन्युअल रूप से सेट किए बिना LINQ क्वेरी परिणाम ऑब्जेक्ट के कुछ गुणों को बदलना चाहता हूं। क्या यह संभव है?

उदाहरण:

var list = from something in someList
           select x // but change one property

7
मैंने नीचे JaredPar के उत्तर पर आधारित एक विस्तार विधि लिखी है, जो आपको मेरे उदाहरण की तरह घोषणात्मक वाक्य रचना का उपयोग करने की अनुमति देता है। इसे देखें: blog.robvolk.com/2009/05/…
Rob Volk

3
@RobVolk, लिंक मृत दिखाई देता है - एक नया मिला? यहां एक संग्रह है - LINQ: एक वस्तु का चयन करें, लेकिन एक नई वस्तु
बनाए

blog.robvolk.com/2009/05/… नहीं मिली DNS त्रुटि
Kiquenet

1
उसके लिए माफ़ करना! ihere का सही पता: robvolk.com/…
Rob Volk

जवाबों:


380

मुझे यकीन नहीं है कि क्वेरी सिंटैक्स क्या है। लेकिन यहाँ विस्तारित LINQ अभिव्यक्ति उदाहरण है।

var query = someList.Select(x => { x.SomeProp = "foo"; return x; })

यह क्या करता है एक अनाम विधि बनाम और अभिव्यक्ति का उपयोग करें। यह आपको एक लैम्ब्डा में कई बयानों का उपयोग करने की अनुमति देता है। तो आप संपत्ति को स्थापित करने और इस कुछ हद तक विधि में वस्तु को वापस करने के दो संचालन को जोड़ सकते हैं।


4
@ रोब, आसानी से नहीं। उस काम को करने के लिए वाक्यविन्यास है ... सबसे अच्छा में अपठनीय। var क्वेरी = सूची में से इसे चुनें ((फंक <फू>) () => {it.x =; इसे वापस लौटें;}) ();
जारेदपार

35
मुझे "स्टेटमेंट के साथ एक लंबोदर अभिव्यक्ति मिल रही है जिसे अभिव्यक्ति ट्री में परिवर्तित नहीं किया जा सकता है" त्रुटि। LINQ to SQL के लिए नहीं, कोई सलाह?
सूर्या

2
आपके लिए @spiderdevil +1 - क्या आपको सिर्फ असमानता से नफरत नहीं है? यह पहली बार नहीं है जब मैंने ऐसी स्थिति में भाग लिया है जहाँ कोड केवल लाइनक टू ऑब्जेक्ट के लिए काम करता है न कि लाइनक टू एसक्यूएल / ईएफ के लिए। यह यहाँ एक समाधान हो सकता है , लेकिन मैंने अभी तक इसका उपयोग करने की कोशिश नहीं की है क्योंकि मेरे पास समय नहीं है।
डिस्लेक्सिकनकोको

11
@surya यह वही संदेश है जो मुझे Linq के साथ SQL की कोशिश करते समय मिला था। ToList()इससे पहले कि जोड़ने के लिए लगता है चाल। सुनिश्चित नहीं हैं कि आपको ऐसा क्यों मिलता है। यदि यह एंटिटी फ्रेमवर्क है, तो यह उसके साथ भी काम नहीं करता है।
रज़िएल

5
जब आप ToList को कॉल करते हैं तो @surya () आप वास्तव में डेटा को वापस मेमोरी में ला रहे हैं। तो यह वास्तव में अब SQL के लिए Linq नहीं है।
ओक

60

यदि आप अभी सभी तत्वों पर संपत्ति को अद्यतन करना चाहते हैं

someList.All(x => { x.SomeProp = "foo"; return true; })

3
ईएफ (एंटिटी फ्रेमवर्क) में: IEnumerable की सभी वस्तुओं पर एक संपत्ति को बदलने के लिए, स्वीकृत जवाब ने मेरे लिए काम किया। मेरे लिए वर्किंग कोड: var myList = _db.MyObjects.Where (o => o.MyProp == "बार")। AsEnumerable ()) का चयन करें (x => {x.SomeProject = "foo"; return x;}) ;
जुगनू

32

मुझे यह पसंद है। इसे अन्य लाइनक कमांड के साथ जोड़ा जा सकता है।

from item in list
let xyz = item.PropertyToChange = calcValue()
select item

24

ऐसा करने से आपको कोई LINQ मैजिक नहीं रखना चाहिए। हालांकि अनाम प्रकार लौटाएंगे, लेकिन प्रक्षेपण का उपयोग न करें।

User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"

यह वास्तविक वस्तु को संशोधित करेगा, साथ ही:

foreach (User u in UserCollection.Where(u => u.Id > 10)
{
    u.Property = SomeValue;
}

मुझे यह पसंद है, मेरा सवाल पहले उदाहरण में है कि क्या कुछ u> 10 सूची में नहीं मिला है? मैंने एक शून्य चेक जोड़ा और काम करने लगता है। इसके अलावा LHS I का नाम u से v। +1 है। बहुत संक्षिप्त।
देसंविव

11

यह मानक क्वेरी ऑपरेटरों के साथ संभव नहीं है - यह भाषा एकीकृत क्वेरी है, न कि भाषा एकीकृत अद्यतन। लेकिन आप अपने अपडेट को विस्तार विधियों में छिपा सकते हैं।

public static class UpdateExtension
{
    public static IEnumerable<Car> ChangeColorTo(
       this IEnumerable<Car> cars, Color color)
    {
       foreach (Car car in cars)
       {
          car.Color = color;
          yield return car;
       }
    }
}

अब आप इसे निम्नानुसार उपयोग कर सकते हैं।

cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);

1
ऐसा नहीं है कि आप आधार संग्रह को अपडेट करना चाहते हैं। हम परिणाम संग्रह संपत्ति को अपडेट करना चाहते हैं।
माइकल ब्रेनट

4
वैसे LINQ SQL को बदलता है जो स्ट्रक्चर्ड क्वेरी लैंग्वेज के लिए है, लेकिन यह अभी भी , और UPDATE, की क्षमता को उजागर करता है । इसलिए मैं यह तर्क नहीं दूंगा कि शब्दार्थ इस कार्य को रोकने वाली चीज है। DELETEINSERT
18

5

यदि आप एक Whereखंड के साथ आइटम अद्यतन करना चाहते हैं , तो (यदि ...) आपके परिणामों को कम कर देगा यदि आप ऐसा करते हैं:

mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();

आप इस तरह की सूची में विशिष्ट आइटम के लिए अपडेट कर सकते हैं:

mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();

यदि आप कोई परिवर्तन नहीं करते हैं तो भी हमेशा आइटम वापस करें। इस तरह इसे सूची में रखा जाएगा।


1

हम अक्सर इसमें भाग लेते हैं जहां हम एक नई वस्तु बनाए बिना एक सूची में सूचकांक मूल्य और पहले और अंतिम संकेतकों को शामिल करना चाहते हैं। इससे आप अपनी सूची में मौजूद वस्तु, पदावनति आदि की स्थिति को जान सकते हैं, बिना मौजूदा वर्ग को संशोधित किए और फिर यह जानकर कि आप सूची में पहले आइटम पर हैं या अंतिम हैं।

foreach (Item item in this.Items
    .Select((x, i) => {
    x.ListIndex = i;
    x.IsFirst = i == 0;
    x.IsLast = i == this.Items.Count-1;
    return x;
}))

आप बस का उपयोग करके किसी भी वर्ग का विस्तार कर सकते हैं:

public abstract class IteratorExtender {
    public int ListIndex { get; set; }
    public bool IsFirst { get; set; } 
    public bool IsLast { get; set; } 
}

public class Item : IteratorExtender {}

0

चूँकि मुझे इसका उत्तर नहीं मिला, जिसे मैं सबसे अच्छा समाधान मानता हूँ, यहाँ मेरा तरीका है:

डेटा को संशोधित करने के लिए "चयन करें" का उपयोग करना संभव है, लेकिन सिर्फ एक चाल के साथ। वैसे भी, "सेलेक्ट" उसके लिए नहीं बना है। यह केवल "ToList" के साथ उपयोग किए जाने पर संशोधन को निष्पादित करता है, क्योंकि डेटा की आवश्यकता होने से पहले Linq का निष्पादन नहीं होता है। वैसे भी, सबसे अच्छा समाधान "फोरच" का उपयोग कर रहा है। निम्नलिखित कोड में, आप देख सकते हैं:

    class Person
    {
        public int Age;
    }

    class Program
    {
        private static void Main(string[] args)
        {
            var persons = new List<Person>(new[] {new Person {Age = 20}, new Person {Age = 22}});
            PrintPersons(persons);

            //this doesn't work:
            persons.Select(p =>
            {
                p.Age++;
                return p;
            });
            PrintPersons(persons);

            //with "ToList" it works
            persons.Select(p =>
            {
                p.Age++;
                return p;
            }).ToList();
            PrintPersons(persons);

            //This is the best solution
            persons.ForEach(p =>
            {
                p.Age++;
            });
            PrintPersons(persons);
            Console.ReadLine();
        }

        private static void PrintPersons(List<Person> persons)
        {
            Console.WriteLine("================");
            foreach (var person in persons)
            {
                Console.WriteLine("Age: {0}", person.Age);
            ;
            }
        }
    }

"Foreach" से पहले, आप एक linq चयन भी कर सकते हैं ...


0
var item = (from something in someList
       select x).firstordefault();

मिल जाएगा item, और फिर आप item.prop1=5;विशिष्ट संपत्ति को बदलने के लिए कर सकते हैं।

या क्या आप db से वस्तुओं की एक सूची प्राप्त करना चाहते हैं और क्या इसने prop1प्रत्येक आइटम पर उस बदले हुए सूची में संपत्ति को एक निर्दिष्ट मूल्य में बदल दिया है? यदि आप ऐसा कर सकते हैं (मैं इसे VB में कर रहा हूं क्योंकि मैं इसे बेहतर जानता हूं):

dim list = from something in someList select x
for each item in list
    item.prop1=5
next

( listआपके परिवर्तनों के साथ लौटाए गए सभी आइटम शामिल होंगे)


जबकि यह काम करेगा, मुझे लगता है कि ओपी पूछ रहा था कि एक for eachलूप लिखने के बिना LINQ स्टेटमेंट कैसे लिखना है ।
फूजीफेस


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.