อัปเดตวัตถุทั้งหมดในชุดรวมโดยใช้ LINQ


500

มีวิธีการทำสิ่งต่อไปนี้โดยใช้ LINQ หรือไม่?

foreach (var c in collection)
{
    c.PropertyToSet = value;
}

เพื่อชี้แจงฉันต้องการย้ำผ่านแต่ละวัตถุในคอลเลกชันแล้วปรับปรุงคุณสมบัติในแต่ละวัตถุ

กรณีการใช้งานของฉันคือฉันมีความคิดเห็นมากมายในบล็อกโพสต์และฉันต้องการย้ำผ่านแต่ละความคิดเห็นในบล็อกโพสต์และตั้งค่าวันที่ในบล็อกโพสต์ให้เป็น +10 ชั่วโมง ฉันสามารถทำได้ใน SQL แต่ฉันต้องการเก็บไว้ในชั้นธุรกิจ


14
คำถามที่น่าสนใจ โดยส่วนตัวแล้วฉันชอบวิธีที่คุณได้รับไป - ชัดเจนยิ่งขึ้นว่าเกิดอะไรขึ้น!
noelicus

8
ฉันมาที่นี่เพื่อค้นหาคำตอบสำหรับคำถามเดียวกันและตัดสินใจว่ามันง่ายเหมือนใช้รหัสน้อยลงและเข้าใจง่ายขึ้นสำหรับผู้พัฒนาในอนาคตที่จะทำในแบบที่คุณทำใน OP
Casey Crookston

4
ทำไมคุณต้องการที่จะทำมันใน LINQ?
Caltor

13
คำถามนี้ถามถึงสิ่งที่ผิดคำตอบที่ถูกต้องคือ: อย่าใช้ LINQ เพื่อแก้ไขแหล่งข้อมูล
Tim Schmelter

ฉันลงคะแนนเพื่อปิดคำถามนี้เป็นนอกหัวข้อเนื่องจากคำตอบเกือบทั้งหมดสำหรับคำถามนี้เป็นอันตรายอย่างมากต่อความเข้าใจในโปรแกรมเมอร์ของ LINQ
Tanveer Badar

คำตอบ:


842

ในขณะที่คุณสามารถใช้ForEachวิธีการขยายหากคุณต้องการใช้เพียงกรอบงานที่คุณสามารถทำได้

collection.Select(c => {c.PropertyToSet = value; return c;}).ToList();

ToListเป็นสิ่งจำเป็นเพื่อประเมินเลือกทันทีเนื่องจากการประเมินผลขี้เกียจ


6
ฉัน upvoting นี้เพราะมันเป็นทางออกที่ดี ... เหตุผลเดียวที่ฉันชอบวิธีการขยายคือมันทำให้ชัดเจนเล็กน้อยที่จะเข้าใจสิ่งที่เกิดขึ้น ... แต่วิธีการแก้ปัญหาของคุณยังคงหวานสวย
lomaxx

9
หากคอลเลกชันเป็นการObservableCollectionพูดการเปลี่ยนแปลงรายการในสถานที่แทนที่จะสร้างรายการใหม่จะมีประโยชน์
Cameron MacFarland

7
@desaivv ใช่นี่เป็นบิตของการละเมิดไวยากรณ์ดังนั้น Resharper เตือนคุณเกี่ยวกับเรื่องนี้
Cameron MacFarland

46
IMHO นี่เป็นการแสดงออกที่น้อยกว่าลูป foreach แบบง่าย ๆ ToList () สับสนเนื่องจากไม่ได้ใช้เพื่ออะไรนอกจากบังคับให้มีการประเมินผลที่จะถูกเลื่อนออกไป การฉายภาพยังทำให้สับสนเพราะมันไม่ได้ใช้ตามวัตถุประสงค์ที่ตั้งใจไว้ ค่อนข้างใช้เพื่อย้ำองค์ประกอบของคอลเลกชันและอนุญาตให้เข้าถึงคุณสมบัติเพื่อให้สามารถอัปเดตได้ คำถามเดียวที่อยู่ในใจของฉันคือว่าวง foreach จะได้ประโยชน์จากการขนานโดยใช้ Parallel.ForEach หรือไม่ แต่นั่นเป็นคำถามที่ต่าง
Philippe

37
คำตอบนี้เป็นการปฏิบัติที่เลวร้ายที่สุด อย่าทำอย่างนี้
Eric Lippert

351
collection.ToList().ForEach(c => c.PropertyToSet = value);

36
@SanthoshKumar: ใช้collection.ToList().ForEach(c => { c.Property1ToSet = value1; c.Property2ToSet = value2; });
ΕГИІИО

@CameronMacFarland: แน่นอนว่ามันจะไม่เกิดขึ้นเนื่องจาก structs ไม่เปลี่ยนรูป แต่ถ้าคุณต้องการจริงๆคุณสามารถทำได้:collection.ToList().ForEach(c => { collection[collection.IndexOf(c)] = new <struct type>() { <propertyToSet> = value, <propertyToRetain> = c.Property2Retain }; });
ΕГИІИО

11
นี่เป็นข้อได้เปรียบเหนือคำตอบของ Cameron MacFarland ในการอัปเดตรายการแทนการสร้างรายการใหม่
Simon Tewsi

7
ว้าวคำตอบนี้ไม่มีประโยชน์จริงๆ สร้างคอลเลกชันใหม่เพื่อให้สามารถใช้ลูปได้
Tim Schmelter

@SimonTewsi เนื่องจากเป็นชุดของวัตถุรายการจึงควรมีการปรับปรุงในสถานที่ต่อไป คอลเลกชันจะใหม่ แต่วัตถุในคอลเลกชันจะเหมือนกัน
Chris

70

ฉันกำลังทำสิ่งนี้

Collection.All(c => { c.needsChange = value; return true; });

ฉันคิดว่านี่เป็นวิธีที่สะอาดที่สุดที่จะทำ
wcm

31
วิธีนี้ใช้งานได้จริง ๆ แต่มันเป็นการละเมิดเจตนาของAll()วิธีการขยายซึ่งนำไปสู่ความสับสนที่อาจเกิดขึ้นเมื่อมีคนอื่นอ่านรหัส
Tom Baxter

วิธีนี้ดีกว่าใช้ทั้งหมดแทนที่จะใช้แต่ละลูป
UJS

2
ชอบสิ่งนี้อย่างแน่นอนมากกว่าการโทร ToList () โดยไม่จำเป็นแม้ว่าจะเป็นการหลอกลวงเล็กน้อยเกี่ยวกับสิ่งที่ใช้ทั้งหมด () สำหรับ
iupchris10

1
หากคุณใช้คอลเลกชันแบบList<>นั้นForEach()วิธีนี้เป็นวิธีที่ลึกลับน้อยกว่ามากในการบรรลุเป้าหมาย อดีตForEach(c => { c.needsChange = value; })
Dan Is Fiddling โดย Firelight

27

ฉันพบวิธีการขยายที่จะทำสิ่งที่ฉันต้องการอย่างแท้จริง

public static IEnumerable<T> ForEach<T>(
    this IEnumerable<T> source,
    Action<T> act)
{
    foreach (T element in source) act(element);
    return source;
}

4
ดี :) Lomaxx อาจเพิ่มตัวอย่างเพื่อให้ peeps สามารถดูได้ใน 'action' (boom tish!)
Pure.Krome

2
นี่เป็นวิธีการที่มีประโยชน์หากคุณต้องการหลีกเลี่ยงการforeach-loop (ด้วยเหตุผลใดก็ตาม)
Tim Schmelter

@Rango ซึ่งคุณยังคงหลีกเลี่ยงไม่ได้foreachเนื่องจากโค้ดนั้นมีforeachลูป
GoldBishop

@ GoldBishop แน่ใจว่าวิธีการซ่อนวง
Tim Schmelter

1
การเชื่อมโยงเสียก็คือตอนนี้มีอยู่ที่: codewrecks.com/blog/index.php/2008/08/13/... นอกจากนี้ยังมีความคิดเห็นบล็อกที่เชื่อมโยงไปยังstackoverflow.com/questions/200574 ในทางกลับกันความคิดเห็นคำถามยอดนิยมเชื่อมโยงไปยัง blogs.msdn.microsoft.com/ericlippert/2009/05/18/… . บางทีคำตอบอาจจะง่ายกว่าการเขียนซ้ำโดยใช้ MSDN (คุณยังสามารถให้เครดิตลิงก์แรกได้หากคุณต้องการ) Sidenote: Rust มีคุณสมบัติที่คล้ายกันและในที่สุดก็ให้ในและเพิ่มฟังก์ชั่นที่เทียบเท่า: stackoverflow.com/a/50224248/799204
sourcejedi

15

ใช้:

ListOfStuff.Where(w => w.Thing == value).ToList().ForEach(f => f.OtherThing = vauleForNewOtherThing);

ฉันไม่แน่ใจว่านี่เป็นการใช้งาน LINQ มากเกินไปหรือไม่ แต่มันได้ผลสำหรับฉันเมื่อต้องการอัปเดตรายการเฉพาะในรายการสำหรับเงื่อนไขเฉพาะ


7

ไม่มีวิธีการขยายในตัวให้ทำเช่นนี้ แม้ว่าการกำหนดอย่างใดอย่างหนึ่งจะค่อนข้างตรงไปข้างหน้า ที่ด้านล่างของโพสต์เป็นวิธีที่ฉันกำหนดไว้เรียกว่า Iterate มันสามารถใช้อย่างนั้น

collection.Iterate(c => { c.PropertyToSet = value;} );

ทำซ้ำแหล่งที่มา

public static void Iterate<T>(this IEnumerable<T> enumerable, Action<T> callback)
{
    if (enumerable == null)
    {
        throw new ArgumentNullException("enumerable");
    }

    IterateHelper(enumerable, (x, i) => callback(x));
}

public static void Iterate<T>(this IEnumerable<T> enumerable, Action<T,int> callback)
{
    if (enumerable == null)
    {
        throw new ArgumentNullException("enumerable");
    }

    IterateHelper(enumerable, callback);
}

private static void IterateHelper<T>(this IEnumerable<T> enumerable, Action<T,int> callback)
{
    int count = 0;
    foreach (var cur in enumerable)
    {
        callback(cur, count);
        count++;
    }
}

การทำซ้ำจำเป็นหรือไม่เกิดอะไรขึ้นกับ Count, Sum, Avg หรือวิธีการขยายอื่น ๆ ที่มีอยู่ซึ่งส่งคืนค่าสเกลาร์
AnthonyWJones

2
มันค่อนข้างใกล้เคียงกับสิ่งที่ฉันต้องการ แต่มีเพียงเล็กน้อย .. ที่เกี่ยวข้อง โพสต์บล็อกที่ฉันโพสต์มีการใช้งานที่คล้ายกัน แต่มีโค้ดน้อยกว่า
lomaxx

1
IterateHelper ดูเหมือนมากเกินไป การโอเวอร์โหลดที่ไม่ใช้ดัชนีทำให้การทำงานพิเศษมากขึ้น (แปลงโทรกลับเป็นแลมบ์ดาซึ่งใช้ดัชนีเก็บจำนวนที่ไม่เคยใช้) ฉันเข้าใจว่ามันใช้ซ้ำได้ แต่มันเป็นวิธีแก้ปัญหาสำหรับการใช้ forloop ต่อไปดังนั้นจึงควรมีประสิทธิภาพ
Cameron MacFarland

2
@Cameron, IterateHelper ให้บริการ 2 วัตถุประสงค์ 1) การใช้งานเดี่ยวและ 2) ช่วยให้ ArgumentNullException ถูกโยนในเวลาที่โทรกับการใช้งาน ตัววนซ้ำ C # ถูกดำเนินการล่าช้าผู้ช่วยจะป้องกันพฤติกรรมผิดปกติของข้อยกเว้นที่ถูกโยนทิ้งในระหว่างการทำซ้ำ
JaredPar

2
@JaredPar: ยกเว้นว่าคุณไม่ได้ใช้ตัววนซ้ำ ไม่มีคำชี้แจงผลตอบแทน
Cameron MacFarland

7

แม้ว่าคุณจะถามวิธีแก้ไขปัญหา LINQ เป็นพิเศษและคำถามนี้ค่อนข้างเก่า แต่ฉันโพสต์ไม่ใช่คำตอบของ LINQ นี่เป็นเพราะ LINQ (= ภาษารวมแบบสอบถาม ) หมายถึงการใช้สำหรับแบบสอบถามในคอลเลกชัน วิธีการ LINQ ทั้งหมดไม่ได้แก้ไขคอลเลกชันพื้นฐานพวกเขาเพียงแค่คืนค่าใหม่ (หรือ iterator ที่แม่นยำยิ่งขึ้นไปยังคอลเลกชันใหม่) ดังนั้นสิ่งที่คุณทำเช่นกับSelectไม่มีผลต่อคอลเลกชันพื้นฐานคุณก็จะได้รับใหม่

แน่นอนว่าคุณสามารถทำได้ด้วยForEach(ซึ่งไม่ใช่ LINQ แต่เป็นส่วนขยายList<T>) แต่นี่ใช้อย่างแท้จริงforeachแต่มีการแสดงออกแลมบ์ดา นอกเหนือจากนี้ทุกวิธี LINQ จะทำซ้ำภายในคอลเลกชันของคุณเช่นโดยการใช้foreachหรือforเพียงแค่ซ่อนจากลูกค้า ฉันไม่คิดว่ามันจะอ่านได้และไม่สามารถบำรุงรักษาได้อีกต่อไป (คิดว่าจะแก้ไขโค้ดของคุณในขณะที่ทำการดีบั๊กวิธีที่มีแลมบ์ดานิพจน์)

ต้องบอกว่าสิ่งนี้ไม่ควรใช้ LINQ เพื่อแก้ไขรายการในคอลเลกชันของคุณ วิธีที่ดีกว่าคือโซลูชันที่คุณให้ไว้ในคำถามของคุณ ด้วยการวนซ้ำแบบคลาสสิกคุณสามารถย้ำคอลเล็กชันของคุณและอัพเดตไอเท็มได้อย่างง่ายดาย อันที่จริงการแก้ปัญหาทั้งหมดที่พึ่งพาList.ForEachนั้นไม่มีอะไรแตกต่างกัน แต่อ่านยากกว่าจากมุมมองของฉัน

ดังนั้นคุณไม่ควรใช้ LINQ ในกรณีที่คุณต้องการอัพเดทองค์ประกอบของคอลเลกชันของคุณ


3
นอกหัวข้อ: ฉันเห็นด้วยและมี sooooooo หลายกรณีที่มีการละเมิด LINQ ตัวอย่างของผู้ที่ร้องขอ "เครือข่าย LINQ ที่มีประสิทธิภาพสูง" เพื่อทำสิ่งที่สามารถทำได้ด้วยการวนรอบเดียวเป็นต้นฉันขอขอบคุณที่ไม่ใช้ LINQ คือ ฝังแน่นเกินไปในฉันและมักจะไม่ใช้มัน ฉันเห็นคนที่ใช้เครือข่าย LINQ เพื่อดำเนินการเพียงครั้งเดียวโดยไม่ทราบว่าสวยทุกครั้งที่มีการใช้คำสั่ง LINQ คุณกำลังสร้างอีกforลูป "ภายใต้ประทุน" ฉันรู้สึกว่ามันเป็นน้ำตาล syntatic ในการสร้างวิธีการทำงานที่เรียบง่ายน้อยลงไม่ได้ใช้แทนการเข้ารหัสมาตรฐาน
ForeverZer0

6

ฉันได้ลองทำสองสามอย่างนี้แล้วฉันจะกลับไปหาทางออกของผู้ชายคนนี้

http://www.hookedonlinq.com/UpdateOperator.ashx

นี่เป็นวิธีแก้ปัญหาของคนอื่น แต่ฉันได้รวบรวมรหัสลงในห้องสมุดขนาดเล็กและใช้มันอย่างสม่ำเสมอ

ฉันจะวางรหัสของเขาที่นี่เพื่อโอกาสที่ไซต์ (บล็อก) ของเขาจะสิ้นสุดลงในอนาคต (ไม่มีอะไรเลวร้ายไปกว่าการเห็นโพสต์ที่ระบุว่า "นี่คือคำตอบที่คุณต้องการ" คลิกและ URL ที่ไม่ต้องเสียค่าใช้จ่าย)

    public static class UpdateExtensions {

    public delegate void Func<TArg0>(TArg0 element);

    /// <summary>
    /// Executes an Update statement block on all elements in an IEnumerable<T> sequence.
    /// </summary>
    /// <typeparam name="TSource">The source element type.</typeparam>
    /// <param name="source">The source sequence.</param>
    /// <param name="update">The update statement to execute for each element.</param>
    /// <returns>The numer of records affected.</returns>
    public static int Update<TSource>(this IEnumerable<TSource> source, Func<TSource> update)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (update == null) throw new ArgumentNullException("update");
        if (typeof(TSource).IsValueType)
            throw new NotSupportedException("value type elements are not supported by update.");

        int count = 0;
        foreach (TSource element in source)
        {
            update(element);
            count++;
        }
        return count;
    }
}



int count = drawingObjects
        .Where(d => d.IsSelected && d.Color == Colors.Blue)
        .Update(e => { e.Color = Color.Red; e.Selected = false; } );

1
คุณสามารถใช้Action<TSource>แทนการสร้างผู้แทนพิเศษ ที่อาจไม่สามารถใช้ได้ในขณะที่เขียนว่า
Frank J

ใช่นั่นคือโรงเรียนเก่า DotNet ในเวลานั้น ความคิดเห็นที่ดีแฟรงค์
granadaCoder

URL นี้ตายแล้ว! (ชื่อโดเมนนี้หมดอายุ) สิ่งที่ดีที่ฉันคัดลอกรหัสที่นี่! #patOnShoulder
granadaCoder

1
การตรวจสอบประเภทของค่าเหมาะสม แต่อาจเป็นการดีกว่าที่จะใช้ข้อ จำกัด เช่นwhere T: structเพื่อจับสิ่งนี้ในเวลารวบรวม
Groo


3

ฉันเขียนวิธีการขยายเพื่อช่วยฉันด้วย

namespace System.Linq
{
    /// <summary>
    /// Class to hold extension methods to Linq.
    /// </summary>
    public static class LinqExtensions
    {
        /// <summary>
        /// Changes all elements of IEnumerable by the change function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="change">The way you want to change the stuff</param>
        /// <returns>An IEnumerable with all changes applied</returns>
        public static IEnumerable<T> Change<T>(this IEnumerable<T> enumerable, Func<T, T> change  )
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(change, "change");

            foreach (var item in enumerable)
            {
                yield return change(item);
            }
        }

        /// <summary>
        /// Changes all elements of IEnumerable by the change function, that fullfill the where function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="change">The way you want to change the stuff</param>
        /// <param name="where">The function to check where changes should be made</param>
        /// <returns>
        /// An IEnumerable with all changes applied
        /// </returns>
        public static IEnumerable<T> ChangeWhere<T>(this IEnumerable<T> enumerable, 
                                                    Func<T, T> change,
                                                    Func<T, bool> @where)
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(change, "change");
            ArgumentCheck.IsNullorWhiteSpace(@where, "where");

            foreach (var item in enumerable)
            {
                if (@where(item))
                {
                    yield return change(item);
                }
                else
                {
                    yield return item;
                }
            }
        }

        /// <summary>
        /// Changes all elements of IEnumerable by the change function that do not fullfill the except function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="change">The way you want to change the stuff</param>
        /// <param name="where">The function to check where changes should not be made</param>
        /// <returns>
        /// An IEnumerable with all changes applied
        /// </returns>
        public static IEnumerable<T> ChangeExcept<T>(this IEnumerable<T> enumerable,
                                                     Func<T, T> change,
                                                     Func<T, bool> @where)
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(change, "change");
            ArgumentCheck.IsNullorWhiteSpace(@where, "where");

            foreach (var item in enumerable)
            {
                if (!@where(item))
                {
                    yield return change(item);
                }
                else
                {
                    yield return item;
                }
            }
        }

        /// <summary>
        /// Update all elements of IEnumerable by the update function (only works with reference types)
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="update">The way you want to change the stuff</param>
        /// <returns>
        /// The same enumerable you passed in
        /// </returns>
        public static IEnumerable<T> Update<T>(this IEnumerable<T> enumerable,
                                               Action<T> update) where T : class
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(update, "update");
            foreach (var item in enumerable)
            {
                update(item);
            }
            return enumerable;
        }

        /// <summary>
        /// Update all elements of IEnumerable by the update function (only works with reference types)
        /// where the where function returns true
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="update">The way you want to change the stuff</param>
        /// <param name="where">The function to check where updates should be made</param>
        /// <returns>
        /// The same enumerable you passed in
        /// </returns>
        public static IEnumerable<T> UpdateWhere<T>(this IEnumerable<T> enumerable,
                                               Action<T> update, Func<T, bool> where) where T : class
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(update, "update");
            foreach (var item in enumerable)
            {
                if (where(item))
                {
                    update(item);
                }
            }
            return enumerable;
        }

        /// <summary>
        /// Update all elements of IEnumerable by the update function (only works with reference types)
        /// Except the elements from the where function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="update">The way you want to change the stuff</param>
        /// <param name="where">The function to check where changes should not be made</param>
        /// <returns>
        /// The same enumerable you passed in
        /// </returns>
        public static IEnumerable<T> UpdateExcept<T>(this IEnumerable<T> enumerable,
                                               Action<T> update, Func<T, bool> where) where T : class
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(update, "update");

            foreach (var item in enumerable)
            {
                if (!where(item))
                {
                    update(item);
                }
            }
            return enumerable;
        }
    }
}

ฉันใช้มันแบบนี้:

        List<int> exampleList = new List<int>()
            {
                1, 2 , 3
            };

        //2 , 3 , 4
        var updated1 = exampleList.Change(x => x + 1);

        //10, 2, 3
        var updated2 = exampleList
            .ChangeWhere(   changeItem => changeItem * 10,          // change you want to make
                            conditionItem => conditionItem < 2);    // where you want to make the change

        //1, 0, 0
        var updated3 = exampleList
            .ChangeExcept(changeItem => 0,                          //Change elements to 0
                          conditionItem => conditionItem == 1);     //everywhere but where element is 1

สำหรับการอ้างอิงการตรวจสอบอาร์กิวเมนต์:

/// <summary>
/// Class for doing argument checks
/// </summary>
public static class ArgumentCheck
{


    /// <summary>
    /// Checks if a value is string or any other object if it is string
    /// it checks for nullorwhitespace otherwhise it checks for null only
    /// </summary>
    /// <typeparam name="T">Type of the item you want to check</typeparam>
    /// <param name="item">The item you want to check</param>
    /// <param name="nameOfTheArgument">Name of the argument</param>
    public static void IsNullorWhiteSpace<T>(T item, string nameOfTheArgument = "")
    {

        Type type = typeof(T);
        if (type == typeof(string) ||
            type == typeof(String))
        {
            if (string.IsNullOrWhiteSpace(item as string))
            {
                throw new ArgumentException(nameOfTheArgument + " is null or Whitespace");
            }
        }
        else
        {
            if (item == null)
            {
                throw new ArgumentException(nameOfTheArgument + " is null");
            }
        }

    }
}

2

2 เพนนีของฉัน: -

 collection.Count(v => (v.PropertyToUpdate = newValue) == null);

7
ฉันชอบความคิด แต่ไม่ชัดเจนว่าโค้ดกำลังทำอะไร
lomaxx

2

คุณสามารถใช้ LINQ เพื่อแปลงคอลเลกชันของคุณเป็นอาร์เรย์จากนั้นเรียกใช้ Array.ForEach ():

Array.ForEach(MyCollection.ToArray(), item=>item.DoSomeStuff());

เห็นได้ชัดว่าสิ่งนี้จะไม่ทำงานกับคอลเลกชันของ structs หรือประเภท inbuilt เช่นจำนวนเต็มหรือสตริง


1

นี่คือวิธีการขยายที่ฉันใช้ ...

    /// <summary>
    /// Executes an Update statement block on all elements in an  IEnumerable of T
    /// sequence.
    /// </summary>
    /// <typeparam name="TSource">The source element type.</typeparam>
    /// <param name="source">The source sequence.</param>
    /// <param name="action">The action method to execute for each element.</param>
    /// <returns>The number of records affected.</returns>
    public static int Update<TSource>(this IEnumerable<TSource> source, Func<TSource> action)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (action == null) throw new ArgumentNullException("action");
        if (typeof (TSource).IsValueType)
            throw new NotSupportedException("value type elements are not supported by update.");

        var count = 0;
        foreach (var element in source)
        {
            action(element);
            count++;
        }
        return count;
    }

เหตุใดจึง "องค์ประกอบของประเภทค่าไม่ได้รับการสนับสนุนโดยการอัพเดต" ไม่มีอะไรมาขัดขวาง!
abatishchev

นั่นเป็นโครงการเฉพาะที่ฉันกำลังทำอยู่ ฉันคิดว่ามันจะไม่สำคัญในกรณีส่วนใหญ่ เมื่อเร็ว ๆ นี้ฉันได้ทำใหม่และเปลี่ยนชื่อเป็น Run (... ) ลบสิ่งที่ประเภทของค่าและเปลี่ยนเป็นคืนเป็นโมฆะและลบรหัสการนับ
Bill Forney

นั่นคือมากกว่าหรือน้อยกว่าสิ่งที่List<T>.ForEachยังไม่ IEnumerableแต่เพียงสำหรับทุก
HimBromBeere

มองย้อนกลับไปตอนนี้ฉันจะบอกว่าใช้วงวน foreach ประโยชน์เพียงอย่างเดียวของการใช้บางอย่างเช่นนี้คือถ้าคุณต้องการรวมเมธอดเข้าด้วยกันและส่งคืนจำนวนที่นับได้จากฟังก์ชั่นเพื่อดำเนินการต่อของโซ่หลังจากรันแอคชัน มิฉะนั้นนี่เป็นเพียงวิธีพิเศษที่เรียกว่าไม่มีประโยชน์
Bill Forney

0

ฉันคิดว่าคุณต้องการเปลี่ยนค่าภายในแบบสอบถามเพื่อให้คุณสามารถเขียนฟังก์ชันได้

void DoStuff()
{
    Func<string, Foo, bool> test = (y, x) => { x.Bar = y; return true; };
    List<Foo> mylist = new List<Foo>();
    var v = from x in mylist
            where test("value", x)
            select x;
}

class Foo
{
    string Bar { get; set; }
}

แต่อย่าคิดว่านี่คือสิ่งที่คุณหมายถึง


นี่กำลังไปในทิศทางที่ถูกต้องโดยจะต้องมีบางอย่างในการแจกแจง v มิฉะนั้นมันจะไม่ทำอะไรเลย
AnthonyWJones


-3

สมมติว่าเรามีข้อมูลด้านล่าง

var items = new List<string>({"123", "456", "789"});
// Like 123 value get updated to 123ABC ..

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

var modifiedItemsList = new List<string>();

items.ForEach(i => {
  var modifiedValue = ModifyingMethod(i);
  modifiedItemsList.Add(items.AsEnumerable().Where(w => w == i).Select(x => modifiedValue).ToList().FirstOrDefault()?.ToString()) 
});
// assign back the modified list
items = modifiedItemsList;

2
ทำไมคุณถึงสร้างบางสิ่งที่สามารถรันในรันไทม์ O (n) รันใน O (n ^ 2) หรือแย่กว่านั้นได้? IM ไม่ทราบว่า linq ทำงานอย่างไร แต่ฉันเห็นได้ว่านี่เป็นวิธีการแก้ปัญหา ^ 2 เป็นอย่างน้อยสำหรับปัญหาn
Fallenreaper
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.