উপাদানের একাধিক সংগ্রহ একত্রিত করার মার্জিত উপায়?


97

বলুন যে আমার কাছে সংগ্রহের একটি স্বেচ্ছাসেবী সংখ্যা রয়েছে, প্রত্যেকটিতে একই ধরণের অবজেক্ট রয়েছে (উদাহরণস্বরূপ, List<int> fooএবং List<int> bar)। যদি এই সংগ্রহগুলি কোনও সংগ্রহের মধ্যে থাকে (যেমন, টাইপের List<List<int>>, আমি SelectManyসেগুলি একত্রে সংগ্রহ করতে ব্যবহার করতে পারি।

তবে, যদি এই সংগ্রহগুলি ইতিমধ্যে একই সংগ্রহে না থাকে, তবে আমার ধারণা যে আমাকে এই জাতীয় পদ্ধতি লিখতে হবে:

public static IEnumerable<T> Combine<T>(params ICollection<T>[] toCombine)
{
   return toCombine.SelectMany(x => x);
}

যা আমি এর পরে কল করব:

var combined = Combine(foo, bar);

Combineউপরের মতো কোনও ইউটিলিটি পদ্ধতি না লিখে সংগ্রহগুলি (যে কোনও সংখ্যক) একত্রিত করার কোনও পরিষ্কার, মার্জিত উপায় আছে ? এটি যথেষ্ট সহজ বলে মনে হচ্ছে এটি লিনকিউতে করার একটি উপায় থাকা উচিত, তবে সম্ভবত তা নয়।



খুব বড় সংখ্যক গণ্যমান্য ব্যক্তির পক্ষে কনক্যাট থেকে সাবধান থাকুন, আপনার স্ট্যাকটি
ফুঁ

উত্তর:


111

আমি মনে করি আপনি লিনকিউ এর সন্ধান করছেন .Concat()?

var combined = foo.Concat(bar).Concat(foobar).Concat(...);

বিকল্পভাবে, .Union()সদৃশ উপাদানগুলি মুছে ফেলবে।


4
ধন্যবাদ; আমি প্রথম স্থানে এটি না করার একমাত্র কারণটি হ'ল (আমার কাছে) মনে হচ্ছে আপনার আরও বেশি সংগ্রহের মুখোমুখি হতে হবে g তবে এটির বিদ্যমান লিনকিউ ফাংশনগুলি ব্যবহার করার সুবিধা রয়েছে, যা ভবিষ্যতের বিকাশকারীরা সম্ভবত ইতিমধ্যে পরিচিত হবে।
ডোনাট

4
টিপটির জন্য ধন্যবাদ .Union()। মনে রাখবেন আপনার আইকোপ্যামারটি আপনার কাস্টম টাইপের ক্ষেত্রে প্রয়োগ করতে হবে
গঞ্জো 345

30

আমার কাছে Concatএক্সটেনশন পদ্ধতি হিসাবে আমার কোডটি খুব মার্জিত হয় না যখন আমার একাধিক বৃহত ক্রম থাকে conc এটি কেবল একটি কোডের ইনডেন্টেশন / ফর্ম্যাটিং সমস্যা এবং খুব ব্যক্তিগত কিছু।

অবশ্যই এটি দেখতে সুন্দর দেখাচ্ছে:

var list = list1.Concat(list2).Concat(list3);

এটি পড়ার মতো নয় যখন এটি পড়তে হয়:

var list = list1.Select(x = > x)
   .Concat(list2.Where(x => true)
   .Concat(list3.OrderBy(x => x));

বা যখন এটির মতো দেখাচ্ছে:

return Normalize(list1, a, b)
    .Concat(Normalize(list2, b, c))
       .Concat(Normalize(list3, c, d));

বা আপনার পছন্দের বিন্যাস যাই হোক না কেন। বিষয়গুলি আরও জটিল কনকোটের সাথে আরও খারাপ হয়। উপরের শৈলীর সাথে আমার ধরণের জ্ঞানীয় অনিয়মের কারণটি হ'ল প্রথম অনুক্রমটি Concatপদ্ধতির বাইরে থাকে যেখানে পরবর্তী অনুক্রমগুলি ভিতরে থাকে। আমি বরং স্থিতিশীল Concatপদ্ধতিটি কল করতে পছন্দ করি না এক্সটেনশন শৈলীতে:

var list = Enumerable.Concat(list1.Select(x => x),
                             list2.Where(x => true));

সিকোয়েন্সের আরও সংখ্যক কনক্যাটসের জন্য আমি ওপি'র মতো একই স্থির পদ্ধতি বহন করি:

public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] sequences)
{
    return sequences.SelectMany(x => x);
}

সুতরাং আমি লিখতে পারি:

return EnumerableEx.Concat
(
    list1.Select(x = > x),
    list2.Where(x => true),
    list3.OrderBy(x => x)
);

ভালো দেখায়. অতিরিক্ত, অন্যথায় অনর্থক, ক্লাসের নামটি আমাকে লিখতে হবে তা আমার জন্য ক্রিয়াকলাপের সাথে আমার সিক্যুয়েন্সগুলি পরিষ্কার মনে করে সমস্যা নয় Concat। এটি সি # 6 তে কোনও সমস্যা কম । আপনি কেবল লিখতে পারেন:

return Concat(list1.Select(x = > x),
              list2.Where(x => true),
              list3.OrderBy(x => x));

আশা করি আমাদের সি # তে তালিকাবদ্ধকরণ অপারেটর রয়েছে, এরকম কিছু:

list1 @ list2 // F#
list1 ++ list2 // Scala

অনেক ক্লিনার সেভাবে।


4
কোডিং শৈলীর জন্য আমি আপনার উদ্বেগের প্রশংসা করি। এটি অনেক বেশি মার্জিত।
ব্রায়ান রায়নার

সম্ভবত আপনার উত্তরের একটি ছোট সংস্করণ এখানে শীর্ষ উত্তরের সাথে একত্রিত করা যেতে পারে।
ব্রায়ান রায়নার

4
আমি এই ফর্ম্যাটটিও পছন্দ করি - যদিও আমি স্বতন্ত্রতার জন্য প্রথমে পৃথক তালিকা অপারেশনগুলি (যেমন Where, OrderBy) সম্পাদন করতে পছন্দ করি , বিশেষত যদি তারা এই উদাহরণের চেয়ে আরও জটিল কিছু হয়।
ব্রিচিন্স 24'17

27

কেস যখন তোমার জন্য কি করতে সংগ্রহ, অর্থাত একটি একটি সংগ্রহ আছে List<List<T>>, Enumerable.Aggregateএক মধ্যে সমস্ত তালিকা একত্রিত করার জন্য আর মার্জিত উপায় হল:

var combined = lists.Aggregate((acc, list) => { return acc.Concat(list); });

4
আপনি কিভাবে listsএখানে প্রথম পাবেন? ওপিতে এটিই প্রথম সমস্যা। তার সাথে যদি collection<collection>শুরু করতে হয় তবে SelectManyএটি সহজ উপায়।
নওফাল

কী হয়েছে তা নিশ্চিত নয়, তবে মনে হচ্ছে এটি ভুল প্রশ্নের উত্তর দিচ্ছে। এটি প্রতিফলিত উত্তর সম্পাদনা। অনেক লোক এখানেই শেষ বলে মনে হচ্ছে কারণ একটি তালিকা <তালিকা <টি>>
এস্ট্রলেটসভ



7

আপনি সর্বদা কনক্যাটের সাথে মিলিত সমষ্টি ব্যবহার করতে পারেন ...

        var listOfLists = new List<List<int>>
        {
            new List<int> {1, 2, 3, 4},
            new List<int> {5, 6, 7, 8},
            new List<int> {9, 10}
        };

        IEnumerable<int> combined = new List<int>();
        combined = listOfLists.Aggregate(combined, (current, list) => current.Concat(list)).ToList();

4
এখন পর্যন্ত সেরা সমাধান।
ওলেগ

@ ওলগ SelectManyকেবল সহজ।
নওফাল

6

আমি দেখতে একমাত্র উপায় ব্যবহার করা হয় Concat()

 var foo = new List<int> { 1, 2, 3 };
 var bar = new List<int> { 4, 5, 6 };
 var tor = new List<int> { 7, 8, 9 };

 var result = foo.Concat(bar).Concat(tor);

তবে আপনারা আরও ভাল যা সিদ্ধান্ত নেবেন:

var result = Combine(foo, bar, tor);

বা

var result = foo.Concat(bar).Concat(tor);

একটি বিষয় কেন Concat()আরও ভাল পছন্দ হবে তা হ'ল এটি অন্য বিকাশকারীর পক্ষে আরও স্পষ্ট। আরও পঠনযোগ্য এবং সাধারণ।


3

আপনি নিম্নলিখিত হিসাবে ইউনিয়ন ব্যবহার করতে পারেন:

var combined=foo.Union(bar).Union(baz)...

এটি অভিন্ন উপাদানগুলি সরিয়ে ফেলবে, তবে আপনার যদি সেগুলি থাকে তবে Concatপরিবর্তে আপনি ব্যবহার করতে চাইতে পারেন ।


4
না! Enumerable.Unionএকটি সেট ইউনিয়ন যা কাঙ্ক্ষিত ফলাফল দেয় না (এটি কেবল একবারে সদৃশ হয়)।
জেসন

হ্যাঁ, আমার অবজেক্টগুলির নির্দিষ্ট দৃষ্টান্তগুলির প্রয়োজন, কারণ সেগুলি সম্পর্কে আমার কিছু বিশেষ প্রসেসিং করা দরকার। intআমার উদাহরণ ব্যবহার করে মানুষকে কিছুটা দূরে ফেলে দিতে পারে; তবে Unionএই ক্ষেত্রে আমার পক্ষে কাজ করবে না।
ডোনাট

2

সংগ্রহ প্রারম্ভিক ব্যবহার করে কয়েকটি কৌশল -

এই তালিকাগুলি ধরে নেওয়া:

var list1 = new List<int> { 1, 2, 3 };
var list2 = new List<int> { 4, 5, 6 };

SelectMany একটি অ্যারে ইনিশিয়ালাইজার সহ (সত্যিই আমার কাছে এটি মার্জিত নয়, তবে কোনও সহায়ক কার্যক্রমে নির্ভর করে না):

var combined = new []{ list1, list2 }.SelectMany(x => x);

যা করতে পারবেন জুড়তে একটি তালিকা এক্সটেনশন নির্ধারণ IEnumerable<T>মধ্যে List<T> সূচনাকারী :

public static class CollectionExtensions
{
    public static void Add<T>(this ICollection<T> collection, IEnumerable<T> items)
    {
        foreach (var item in items) collection.Add(item);
    }
}

তারপরে আপনি এই জাতীয় অন্যদের উপাদান যুক্ত একটি নতুন তালিকা তৈরি করতে পারেন (এটি একক আইটেমগুলিকেও মিশ্রিত করতে দেয়)।

var combined = new List<int> { list1, list2, 7, 8 };

1

আপনি পৃথক সংগ্রহের একগুচ্ছ দিয়ে শুরু করছেন তা দেওয়া, আমি মনে করি আপনার সমাধানটি বরং মার্জিত। এগুলি একসাথে সেলাই করার জন্য আপনাকে কিছু করতে হবে ।

আপনার সম্মিলন পদ্ধতি থেকে এক্সটেনশন পদ্ধতি তৈরি করা সিনথেটিকভাবে আরও সুবিধাজনক হবে, এটি আপনার যেদিকে যে কোনও জায়গায় পাওয়া যায়।


আমি এক্সটেনশন পদ্ধতি ধারণা মত, আমি শুধু নেই (আরও লাইন নিচে অন্যান্য বিকাশকারীদের কাছে বোধগম্য প্রয়োজন এবং হতে অবিলম্বে) চাকা reinvent LINQ ইতিমধ্যে একটি পদ্ধতি যা একই জিনিস করে করতেন যদি চায়নি
ডোনাট

1

আপনার যা প্রয়োজন তা হ'ল যে কোনওটির জন্য IEnumerable<IEnumerable<T>> lists:

var combined = lists.Aggregate((l1, l2) => l1.Concat(l2));

এটি সমস্ত আইটেম listsএক সাথে IEnumerable<T>(ডুপ্লিকেট সহ) একত্রিত করবে । অন্যান্য উত্তরে উল্লিখিত হিসাবে সদৃশ অপসারণের Unionপরিবর্তে ব্যবহার করুন Concat

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.