একটি সংগ্রহকে Q n` ভাগগুলিতে ভাগ করুন LINQ দিয়ে?


122

কোনও সংগ্রহকে nলিনকুতে ভাগ করার জন্য কি কোনও দুর্দান্ত উপায় আছে ? অগত্যা অবশ্যই সমানভাবে নয়।

এটি হ'ল, আমি সংগ্রহটি উপ-সংগ্রহগুলিতে বিভক্ত করতে চাই, যার প্রতিটিটিতে উপাদানগুলির একটি উপসেট রয়েছে, যেখানে শেষ সংগ্রহটি র‌্যাগ করা যায়।


1
পুনরায় সংশোধন করা হয়েছে: প্রশ্নটির অ্যাপ নেটওয়ারের সাথে কোনও সম্পর্ক নেই। আপনার প্রশ্নগুলি যথাযথভাবে ট্যাগ করুন।

আপনি ঠিক কীভাবে এগুলি বিভক্ত করতে চান, তা না হলেও (অবশ্যই শেষের জন্য অনুমতি দিচ্ছেন)?
মার্ক Gravell

1
কে এই প্রশ্নের সাথে যুক্ত? জন আপনি কি ছিলেন? :-) হঠাৎ এই সমস্ত উত্তর :-)
সায়মন_উইভার 21'৯৯


@ সিমন_আমি যাইহোক আমি স্বীকার করা উত্তরের ভিত্তিতে আপনি যা জিজ্ঞাসা করছেন তা পরিষ্কার করার চেষ্টা করেছি tried প্রকৃতপক্ষে তালিকার প্রতিটি উপাদানকে এর উপাদানগুলিতে ডেকোপস করা এবং সেগুলিকে তথাকথিত 'সমান্তরাল' তালিকায় অন্তর্ভুক্ত করে একটি তালিকা 'বিভক্ত' করার অনেকগুলি উপায় রয়েছে।
jpaugh

উত্তর:


127

একটি খাঁটি লিনাক এবং সহজ সমাধান নীচে দেখানো হয়েছে।

static class LinqExtensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
    {
        int i = 0;
        var splits = from item in list
                     group item by i++ % parts into part
                     select part.AsEnumerable();
        return splits;
    }
}

3
আপনি এটি করতে পারেন: অংশটি নির্বাচন করুন selectআনামিউরেবল () এর পরিবর্তে (আইএনিউমারেবল <T>) অংশটি নির্বাচন করুন। এটি আরও মার্জিত মনে হয়।
tuinstoel

2
এই সমস্ত মডুলাস অপারেশনগুলি করা দীর্ঘ তালিকাতে কিছুটা ব্যয়বহুল হতে পারে।
জোনাথন অ্যালেন

8
ইন্ডেক্সটি অন্তর্ভুক্ত করুন ওভারলোড নির্বাচন করুন ব্যবহার করা ভাল।
মার্ক গ্র্যাভেল

1
আমি একটি প্রতিক্রিয়া যুক্ত করেছি যা নির্বাচিত ওভারলোড এবং পদ্ধতি
চেইন

1
.AsEnumerable()প্রয়োজনীয় নয়, আইগ্রুপিং <T> ইতিমধ্যে একটি অনুমিত <টি>।
অ্যালেক্স

58

সম্পাদনা: ঠিক আছে, দেখে মনে হচ্ছে আমি প্রশ্নটি ভুলভাবে পড়েছি। আমি এটিকে "এন টুকরো" এর পরিবর্তে "দৈর্ঘ্যের টুকরা এন" হিসাবে পড়ি। ডোহ! উত্তর মোছার বিষয়টি বিবেচনা করে ...

(আসল উত্তর)

আমি বিশ্বাস করি না যে বিভাজনের একটি অন্তর্নির্মিত উপায় আছে, যদিও আমি লিনকিউতে আমার সংযোজনগুলির সেটগুলিতে অবজেক্টে লিখতে চাইছি। মার্ক গ্র্যাভেলের এখানে একটি বাস্তবায়ন রয়েছে যদিও আমি সম্ভবত এটি কেবলমাত্র পঠনযোগ্য দর্শন ফিরিয়ে দিতে সংশোধন করব:

public static IEnumerable<IEnumerable<T>> Partition<T>
    (this IEnumerable<T> source, int size)
{
    T[] array = null;
    int count = 0;
    foreach (T item in source)
    {
        if (array == null)
        {
            array = new T[size];
        }
        array[count] = item;
        count++;
        if (count == size)
        {
            yield return new ReadOnlyCollection<T>(array);
            array = null;
            count = 0;
        }
    }
    if (array != null)
    {             
        Array.Resize(ref array, count);
        yield return new ReadOnlyCollection<T>(array);
    }
}

ডার্ন - আমাকে এটি মারধর করুন ;
মার্ক

3
আপনি সত্যিই সেই "অ্যারে [গণনা ++]" পছন্দ করেন না, এহ ;
মার্ক গ্র্যাভেল

18
মুছে ফেলার জন্য আপনাকে ধন্যবাদ না যদিও এটি ওপির কোনও উত্তর নয়, আমি ঠিক একই জিনিসটি চেয়েছিলাম - দৈর্ঘ্যের টুকরা :)।
গিশু

2
@ দেজন: না তা হয় না। এর ব্যবহারটি নোট করুন yield return। এটি একবারে স্মৃতিতে থাকা একটি ব্যাচ প্রয়োজন, তবে এটিই যথেষ্ট ।
জন স্কিটি

1
@ দেজন: ঠিক - আমি কীভাবে এটি প্যারালাল লিনকিউ বিভাজনের সাথে মিথস্ক্রিয়া নিয়ে মিথ্যা ধারণা করতে চাই না, সত্যি বলতে :)
জন স্কিটি

39
static class LinqExtensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
    {
            return list.Select((item, index) => new {index, item})
                       .GroupBy(x => x.index % parts)
                       .Select(x => x.Select(y => y.item));
    }
}

28
আমার এসকিউএল-স্টাইলের লিনক সম্পর্কে অযৌক্তিক অপছন্দ, তাই এটি আমার প্রিয় উত্তর।
পিয়াদার

1
@ manu08, আমি আপনার কোড চেষ্টা করেছি, আমার একটি তালিকা আছে var dept = {1,2,3,4,5}। বিভক্ত হওয়ার পরে ফলাফলটি কোথায় dept1 = {1,3,5}এবং dept2 = { 2,4 }কোথায় হয় parts = 2। কিন্তু প্রয়োজন আমি ফল dept1 = {1,2,3}এবংdept2 = {4,5}
কার্তিক Arthik

3
আমি মডিউল সঙ্গে একই সমস্যা ছিল, তাই আমি কলাম দৈর্ঘ্য হিসাব দিয়ে int columnLength = (int)Math.Ceiling((decimal)(list.Count()) / parts);তারপর বিভাজন করেনি .GroupBy(x => x.index / columnLength)। একটি নেতিবাচক নাম গণনা () তালিকা enumerates।
গুদেডে

24

ঠিক আছে, আমি আমার টুপিটি রিংয়ে ফেলে দেব। আমার অ্যালগরিদমের সুবিধা:

  1. কোনও ব্যয়বহুল গুণ, বিভাগ বা মডুলাস অপারেটর নেই
  2. সমস্ত ক্রিয়াকলাপ হ'ল (1) (নীচের নোট দেখুন)
  3. অনুমিত <> উত্সের জন্য কাজ করে (কোনও গণনার সম্পত্তি প্রয়োজন নেই)
  4. সহজ

কোড:

public static IEnumerable<IEnumerable<T>>
  Section<T>(this IEnumerable<T> source, int length)
{
  if (length <= 0)
    throw new ArgumentOutOfRangeException("length");

  var section = new List<T>(length);

  foreach (var item in source)
  {
    section.Add(item);

    if (section.Count == length)
    {
      yield return section.AsReadOnly();
      section = new List<T>(length);
    }
  }

  if (section.Count > 0)
    yield return section.AsReadOnly();
}

নীচের মন্তব্যে নির্দেশিত হিসাবে, এই পদ্ধতির প্রকৃতপক্ষে মূল প্রশ্নটিকে সম্বোধন করে না যা প্রায় সমান দৈর্ঘ্যের বিভাগগুলির একটি নির্দিষ্ট সংখ্যার জন্য জিজ্ঞাসা করেছিল। এটি বলেছে, আপনি এখনও আমার প্রশ্নটি এইভাবে কল করে মূল প্রশ্নটি সমাধান করতে পারেন:

myEnum.Section(myEnum.Count() / number_of_sections + 1)

এই পদ্ধতিতে ব্যবহার করার সময়, গণনা () অপারেশনটি ও (এন) হওয়ায় পদ্ধতির আর ও (1) থাকে না।


উজ্জ্বল - সেরা সমাধান এখানে! কয়েকটি অপ্টিমাইজেশন: * প্রতিটি বিভাগের জন্য একটি নতুন তৈরি করার পরিবর্তে লিঙ্কযুক্ত তালিকা সাফ করুন। লিঙ্কযুক্ত তালিকার কোনও রেফারেন্স কলারে কখনই ফিরে আসে না, তাই এটি সম্পূর্ণ নিরাপদ। * আপনি প্রথম আইটেমটি না পৌঁছানো পর্যন্ত লিঙ্কযুক্ত তালিকাটি তৈরি করবেন না
উত্সটি

3
@ শ্যাডোচ্যাজার এমএসডিএন অনুসারে লিঙ্কডলিস্ট সাফ করা ও (এন) জটিলতা তাই এটি আমার ও (১) এর লক্ষ্যকে নষ্ট করবে। অবশ্যই, আপনি তর্ক করতে পারেন যে পূর্বাভাসটি হ'ল (এন) দিয়ে শুরু করা হবে ... :)
মাইক

4
আপনার উত্তরটি সঠিক, তবে এটির জন্য প্রশ্নটি ভুল। আপনার উত্তরটি প্রতিটি অংশের জন্য নির্দিষ্ট আকারের অজানা সংখ্যা দেয় gives তবে ওপি একটি স্প্লিট কার্যকারিতা চায় যেখানে এটি প্রতি অংশের যে কোনও আকারের সমান সংখ্যক নির্দিষ্ট সংখ্যক অংশ দেয় (আশা করি সমান আকারের সমান বা নিকটে)। সম্ভবত এখানে উপযুক্ত stackoverflow.com/questions/3773403/...
nawfal

1
@ মাইক আপনি এটি বেঞ্চমার্ক করেছেন? আমি আশা করি আপনি ও (1) এর অর্থ দ্রুত নয়, এটির অর্থ কেবলমাত্র পার্টিশনের জন্য প্রয়োজনীয় সময়টি মাপেনি। আমি কেবল ভাবছি যে অনন্যভাবে O (1) এ আঁকড়ে থাকার কী যুক্তি আপনার বাস্তব জীবনের পরিস্থিতিতে যখন অন্যান্য ও (এন) এর চেয়ে ধীর হতে পারে তখন। এমনকি আমি এটি একটি পাগল 10 ^ 8 শক্তি তালিকার জন্যও পরীক্ষা করেছি এবং আমার কাছে আরও তাত্পর্যপূর্ণ প্রদর্শিত হয়েছে। আমি আশা করি আপনি জানেন যে এমন কোনও স্ট্যান্ডার্ড সংগ্রহের
ধরণেরও নেই যা

1
@ নওফাল - আপনার বিশদ বিশ্লেষণের জন্য আপনাকে ধন্যবাদ, এটি আমাকে আমার পায়ের আঙ্গুলগুলিতে রাখতে সহায়তা করে। সাধারণত লিঙ্কযুক্ত তালিকাগুলি দক্ষ শেষ-সন্নিবেশকারীদের জন্য পরিচিত, এই কারণেই আমি এটি এখানে নির্বাচন করেছি। তবে আমি কেবল এটি বেঞ্চমার্ক করেছি এবং প্রকৃতপক্ষে তালিকা <> আরও দ্রুত। আমি সন্দেহ করি এটি নেট রেকর্ড বাস্তবায়ন বিশদ কিছু ধরণের, সম্ভবত একটি পৃথক স্ট্যাকওভারফ্লো প্রশ্নের উপযুক্ত। আমি আপনার পরামর্শ অনুসারে তালিকা <> ব্যবহার করার জন্য আমার উত্তরটি পরিবর্তন করেছি। তালিকার ক্ষমতার পূর্বে প্রচার করা গ্যারান্টি দেয় যে শেষ সন্নিবেশ এখনও ও (1) এবং আমার মূল নকশা লক্ষ্য পূরণ করে। আমি অন্তর্নির্মিত .এসআরডঅনলি () .NET 4.5 এ স্যুইচ করেছি।
মাইক

16

এটি গৃহীত উত্তর হিসাবে একই, তবে অনেক সহজ উপস্থাপনা:

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items, 
                                                   int numOfParts)
{
    int i = 0;
    return items.GroupBy(x => i++ % numOfParts);
}

উপরের পদ্ধতিটি একটি IEnumerable<T>সমান মাপের অংশ বা সমান আকারের কাছাকাছি N সংখ্যায় বিভক্ত করে ।

public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> items, 
                                                       int partitionSize)
{
    int i = 0;
    return items.GroupBy(x => i++ / partitionSize).ToArray();
}

উপরের পদ্ধতিটি একটি বিভক্ত IEnumerable<T> কাঙ্ক্ষিত স্থির আকারের অংশগুলিতে করে মোট অংশগুলি গুরুত্বহীন - যা প্রশ্নটি নয় তা নয়।

সমস্যাটি Splitপদ্ধতিটির ধীর হওয়া ছাড়াও হ'ল আউটপুটটি স্ক্র্যামবিল করে এই অর্থে যে গ্রুপিংটি প্রতিটি পদের জন্য এন এর একাধিকের ভিত্তিতে করা হবে, বা অন্য কথায় আপনি খণ্ডগুলি পাবেন না মূল ক্রমে।

এখানে প্রায় প্রতিটি উত্তর হয় অর্ডার সংরক্ষণ করে না, বা বিভাজন সম্পর্কে এবং বিভাজন সম্পর্কে নয়, বা স্পষ্টতই ভুল। এটি দ্রুত যা চেষ্টা করুন, অর্ডার সংরক্ষণ করে তবে একটি লিল 'আরও ভার্বোস:

public static IEnumerable<IEnumerable<T>> Split<T>(this ICollection<T> items, 
                                                   int numberOfChunks)
{
    if (numberOfChunks <= 0 || numberOfChunks > items.Count)
        throw new ArgumentOutOfRangeException("numberOfChunks");

    int sizePerPacket = items.Count / numberOfChunks;
    int extra = items.Count % numberOfChunks;

    for (int i = 0; i < numberOfChunks - extra; i++)
        yield return items.Skip(i * sizePerPacket).Take(sizePerPacket);

    int alreadyReturnedCount = (numberOfChunks - extra) * sizePerPacket;
    int toReturnCount = extra == 0 ? 0 : (items.Count - numberOfChunks) / extra + 1;
    for (int i = 0; i < extra; i++)
        yield return items.Skip(alreadyReturnedCount + i * toReturnCount).Take(toReturnCount);
}

এখানে একটি Partitionঅপারেশন জন্য সমতুল্য পদ্ধতি


6

আমি প্রায়শই প্রায়শই পোস্ট করা পার্টিশন ফাংশনটি ব্যবহার করে আসছি। এটি সম্পর্কে কেবল খারাপ জিনিসটি ছিল সম্পূর্ণ স্ট্রিমিং নয়। আপনি যদি নিজের অনুক্রমের কয়েকটি উপাদান নিয়ে কাজ করেন তবে এটি কোনও সমস্যা নয়। যখন আমি আমার অনুক্রমের 100.000+ উপাদানগুলির সাথে কাজ শুরু করি তখন আমার একটি নতুন সমাধান প্রয়োজন।

নিম্নলিখিত সমাধানটি অনেক বেশি জটিল (এবং আরও কোড!) তবে এটি খুব কার্যকরী।

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

namespace LuvDaSun.Linq
{
    public static class EnumerableExtensions
    {
        public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> enumerable, int partitionSize)
        {
            /*
            return enumerable
                .Select((item, index) => new { Item = item, Index = index, })
                .GroupBy(item => item.Index / partitionSize)
                .Select(group => group.Select(item => item.Item)                )
                ;
            */

            return new PartitioningEnumerable<T>(enumerable, partitionSize);
        }

    }


    class PartitioningEnumerable<T> : IEnumerable<IEnumerable<T>>
    {
        IEnumerable<T> _enumerable;
        int _partitionSize;
        public PartitioningEnumerable(IEnumerable<T> enumerable, int partitionSize)
        {
            _enumerable = enumerable;
            _partitionSize = partitionSize;
        }

        public IEnumerator<IEnumerable<T>> GetEnumerator()
        {
            return new PartitioningEnumerator<T>(_enumerable.GetEnumerator(), _partitionSize);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }


    class PartitioningEnumerator<T> : IEnumerator<IEnumerable<T>>
    {
        IEnumerator<T> _enumerator;
        int _partitionSize;
        public PartitioningEnumerator(IEnumerator<T> enumerator, int partitionSize)
        {
            _enumerator = enumerator;
            _partitionSize = partitionSize;
        }

        public void Dispose()
        {
            _enumerator.Dispose();
        }

        IEnumerable<T> _current;
        public IEnumerable<T> Current
        {
            get { return _current; }
        }
        object IEnumerator.Current
        {
            get { return _current; }
        }

        public void Reset()
        {
            _current = null;
            _enumerator.Reset();
        }

        public bool MoveNext()
        {
            bool result;

            if (_enumerator.MoveNext())
            {
                _current = new PartitionEnumerable<T>(_enumerator, _partitionSize);
                result = true;
            }
            else
            {
                _current = null;
                result = false;
            }

            return result;
        }

    }



    class PartitionEnumerable<T> : IEnumerable<T>
    {
        IEnumerator<T> _enumerator;
        int _partitionSize;
        public PartitionEnumerable(IEnumerator<T> enumerator, int partitionSize)
        {
            _enumerator = enumerator;
            _partitionSize = partitionSize;
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new PartitionEnumerator<T>(_enumerator, _partitionSize);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }


    class PartitionEnumerator<T> : IEnumerator<T>
    {
        IEnumerator<T> _enumerator;
        int _partitionSize;
        int _count;
        public PartitionEnumerator(IEnumerator<T> enumerator, int partitionSize)
        {
            _enumerator = enumerator;
            _partitionSize = partitionSize;
        }

        public void Dispose()
        {
        }

        public T Current
        {
            get { return _enumerator.Current; }
        }
        object IEnumerator.Current
        {
            get { return _enumerator.Current; }
        }
        public void Reset()
        {
            if (_count > 0) throw new InvalidOperationException();
        }

        public bool MoveNext()
        {
            bool result;

            if (_count < _partitionSize)
            {
                if (_count > 0)
                {
                    result = _enumerator.MoveNext();
                }
                else
                {
                    result = true;
                }
                _count++;
            }
            else
            {
                result = false;
            }

            return result;
        }

    }
}

উপভোগ করুন!


এই সংস্করণটি আইইনমিটারের চুক্তি ভঙ্গ করে। রিসেট বলা হয়ে গেলে অবৈধ অপশন এক্সেক্সশনটি নিক্ষেপ করা বৈধ নয় - আমি বিশ্বাস করি যে অনেকগুলি লিনকিউ এক্সটেনশন পদ্ধতি এই আচরণের উপর নির্ভর করে।
শ্যাডোচ্যাজার

1
@ শ্যাডোচ্যাজার আমি মনে করি রিসেটের () একটি নটসম্পোর্টড এক্সসেপশন নিক্ষেপ করা উচিত এবং সবকিছু ঠিকঠাক হবে। এমএসডিএন ডকুমেন্টেশন থেকে: "রিসেট পদ্ধতিটি সিওএম আন্তঃব্যবহারযোগ্যতার জন্য সরবরাহ করা হয় It এটি কার্যকরভাবে প্রয়োগ করার প্রয়োজন হয় না; পরিবর্তে, প্রয়োগকারী কেবল একটি নটসপোর্টড এক্সসেপশন নিক্ষেপ করতে পারে।"
টুং

@ টু ওয়া, আপনি ঠিক বলেছেন এতক্ষণের পরেও কীভাবে আমি এটি মিস করেছি তা নিশ্চিত নয়।
শ্যাডোচ্যাজার

এটা বগি! আমি ঠিক মনে করি না, তবে (যতদূর আমি মনে করি) এটি অযাচিত পদক্ষেপটি সম্পাদন করে এবং এটি কুৎসিত পার্শ্ব প্রতিক্রিয়া হতে পারে (প্রাক্তনের জন্য ডেটারিডারের সাথে।) : সবচেয়ে ভালো সমাধান এখানে (Jeppe Stig নিলসেন) হল stackoverflow.com/questions/13709626/...
SalientBrain

4

আকর্ষণীয় থ্রেড। স্প্লিট / পার্টিশনের একটি স্ট্রিমিং সংস্করণ পেতে, কেউ এক্সটেনশন পদ্ধতি ব্যবহার করে গণকের কাছ থেকে গণক ব্যবহার করতে পারেন এবং ক্রম উত্পাদন করতে পারবেন। জরুরী কোডটি ফলন ব্যবহার করে ক্রিয়ামূলক কোডে রূপান্তর করা সত্যিই খুব শক্তিশালী একটি কৌশল।

প্রথমে একটি গণকের এক্সটেনশান যা উপাদানগুলির একটি গণনাটিকে অলস অনুক্রমে পরিণত করে:

public static IEnumerable<T> TakeFromCurrent<T>(this IEnumerator<T> enumerator, int count)
{
    while (count > 0)
    {
        yield return enumerator.Current;
        if (--count > 0 && !enumerator.MoveNext()) yield break;
    }
}

এবং তারপরে একটি সংখ্যাযুক্ত এক্সটেনশন যা একটি সিকোয়েন্সকে পার্টিশন করে:

public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> seq, int partitionSize)
{
    var enumerator = seq.GetEnumerator();

    while (enumerator.MoveNext())
    {
        yield return enumerator.TakeFromCurrent(partitionSize);
    }
}

শেষ ফলাফলটি একটি অত্যন্ত দক্ষ, স্ট্রিমিং এবং অলস বাস্তবায়ন যা খুব সাধারণ কোডের উপর নির্ভর করে।

উপভোগ করুন!


আমি প্রথমে একই জিনিসটি প্রোগ্রাম করেছিলাম, তবে নেস্টেড আইমেন্টামেন্ট <T> দৃষ্টান্তগুলির মধ্যে রিসেটটি কল করা হলে প্যাটার্নটি ভেঙে যায়।
শ্যাডোচেসার

1
আপনি যদি কেবলমাত্র পার্টিশনটি গণনা করেন তবে অভ্যন্তরীণ গণনা করা যায় না তা কি এখনও কাজ করে? যেহেতু অভ্যন্তরীণ গণকটি স্থগিত হয়ে গেছে, সুতরাং অভ্যন্তরের কোনও কোডই (বর্তমান থেকে নেওয়া) কার্যকর হবে না যতক্ষণ না এটি গণনা করা হয় তাই মুভনেক্সট () কেবল বাহ্যিক পার্টিশন ফাংশন দ্বারা ডাকা হবে, তাই না? যদি আমার অনুমানগুলি সত্য হয় তবে এটি সম্ভাব্যভাবে মূল সংখ্যাগুলিতে এন উপাদানগুলির সাথে এন পার্টিশনগুলি আনতে পারে এবং অভ্যন্তরীণ সংখ্যাগুলি অপ্রত্যাশিত ফলাফল আনতে পারে
ব্র্যাড

@Brad এটি "ব্যর্থ" করবে আশা, এই থ্রেড বিষয় কিছু অনুরূপ যেমন stackoverflow.com/questions/419019/... (বিশেষভাবে stackoverflow.com/a/20953521/1037948 )
drzaus

4

আমি এটি ব্যবহার:

public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> instance, int partitionSize)
{
    return instance
        .Select((value, index) => new { Index = index, Value = value })
        .GroupBy(i => i.Index / partitionSize)
        .Select(i => i.Select(i2 => i2.Value));
}

কেন দয়া করে ব্যাখ্যা করুন। আমি কোনও ঝামেলা ছাড়াই এই ফাংশনটি ব্যবহার করছি!
এলমার

প্রশ্নটি আবার পড়ুন এবং দেখুন আপনার ফাংশনটির সাথে সমান দৈর্ঘ্যের অংশগুলি (প্রায়) পান কিনা
মুহাম্মদ হাসান খান

@ এলমার আপনার উত্তরটি সঠিক, তবে এটির জন্য প্রশ্নটি ভুল। আপনার উত্তর প্রতিটি অংশের জন্য নির্দিষ্ট আকারের অজানা সংখ্যক অংশকে দেয় (ঠিক পার্টিশন হিসাবে, আপনি এটির জন্য নাম দিয়েছেন)। তবে ওপি একটি স্প্লিট কার্যকারিতা চায় যেখানে এটি প্রতি অংশের যে কোনও আকারের সমান সংখ্যক নির্দিষ্ট সংখ্যক অংশ দেয় (আশা করি সমান আকারের সমান বা নিকটে)। সম্ভবত এখানে উপযুক্ত stackoverflow.com/questions/3773403/...
nawfal

আমি মনে করি আপনি কেবল i.Index / পার্টিশনসাইজকে i.Index% পার্টিশনসাইজে পরিবর্তন করতে পারেন এবং অনুরোধিত ফলাফল পেতে পারেন। আমি এটি গ্রহণযোগ্য উত্তরের চেয়েও বেশি পছন্দ করি কারণ এটি আরও কমপ্যাক্ট এবং পাঠযোগ্য।
জেক ড্র 16

2

এটি মেমরি দক্ষ এবং যথাসম্ভব কার্যকর করা স্থগিত করে (প্রতি ব্যাচ) এবং রৈখিক সময়ে পরিচালনা করে হে (এন)

    public static IEnumerable<IEnumerable<T>> InBatchesOf<T>(this IEnumerable<T> items, int batchSize)
    {
        List<T> batch = new List<T>(batchSize);
        foreach (var item in items)
        {
            batch.Add(item);

            if (batch.Count >= batchSize)
            {
                yield return batch;
                batch = new List<T>();
            }
        }

        if (batch.Count != 0)
        {
            //can't be batch size or would've yielded above
            batch.TrimExcess();
            yield return batch;
        }
    }

2

এই প্রশ্নের (এবং এর কাজিন্স) জন্য প্রচুর দুর্দান্ত উত্তর রয়েছে। আমার নিজের এটির প্রয়োজন ছিল এবং এমন একটি সমাধান তৈরি করেছিলাম যা এমন দৃশ্যে দক্ষ এবং ত্রুটি সহনশীল হওয়ার জন্য ডিজাইন করা হয়েছে যেখানে উত্স সংগ্রহটি একটি তালিকা হিসাবে বিবেচনা করা যেতে পারে। এটি কোনও অলস পুনরাবৃত্তি ব্যবহার করে না তাই এটি অজানা আকারের সংগ্রহের জন্য উপযুক্ত নাও হতে পারে যা মেমরির চাপ প্রয়োগ করতে পারে।

static public IList<T[]> GetChunks<T>(this IEnumerable<T> source, int batchsize)
{
    IList<T[]> result = null;
    if (source != null && batchsize > 0)
    {
        var list = source as List<T> ?? source.ToList();
        if (list.Count > 0)
        {
            result = new List<T[]>();
            for (var index = 0; index < list.Count; index += batchsize)
            {
                var rangesize = Math.Min(batchsize, list.Count - index);
                result.Add(list.GetRange(index, rangesize).ToArray());
            }
        }
    }
    return result ?? Enumerable.Empty<T[]>().ToList();
}

static public void TestGetChunks()
{
    var ids = Enumerable.Range(1, 163).Select(i => i.ToString());
    foreach (var chunk in ids.GetChunks(20))
    {
        Console.WriteLine("[{0}]", String.Join(",", chunk));
    }
}

আমি এই প্রশ্নের কয়েকটি পরিবার জুড়ে দেখেছি যা গেটর্যাঞ্জ এবং ম্যাথ.মিন ব্যবহার করে। তবে আমি বিশ্বাস করি যে সামগ্রিকভাবে এটি ত্রুটি যাচাই এবং দক্ষতার দিক থেকে আরও সম্পূর্ণ সমাধান।


1
   protected List<List<int>> MySplit(int MaxNumber, int Divider)
        {
            List<List<int>> lst = new List<List<int>>();
            int ListCount = 0;
            int d = MaxNumber / Divider;
            lst.Add(new List<int>());
            for (int i = 1; i <= MaxNumber; i++)
            {
                lst[ListCount].Add(i);
                if (i != 0 && i % d == 0)
                {
                    ListCount++;
                    d += MaxNumber / Divider;
                    lst.Add(new List<int>());
                }
            }
            return lst;
        }

1

দুর্দান্ত উত্তর, আমার দৃশ্যের জন্য আমি স্বীকৃত উত্তরটি পরীক্ষা করেছি এবং দেখে মনে হচ্ছে এটি অর্ডার রাখে না। নওফালের দুর্দান্ত উত্তরও রয়েছে যা শৃঙ্খলা রাখে। তবে আমার দৃশ্যে আমি বাকী অংশগুলিকে একটি স্বাভাবিক উপায়ে ভাগ করতে চেয়েছিলাম, আমি যে সমস্ত উত্তর দেখেছি সেগুলি বাকী বা শুরুতে বা শেষে ছড়িয়ে দিয়েছে।

আমার উত্তরটি বাকী বাকী অংশগুলিকে আরও সাধারণভাবে গ্রহণ করে।

 static class Program
{          
    static void Main(string[] args)
    {
        var input = new List<String>();
        for (int k = 0; k < 18; ++k)
        {
            input.Add(k.ToString());
        }
        var result = splitListIntoSmallerLists(input, 15);            
        int i = 0;
        foreach(var resul in result){
            Console.WriteLine("------Segment:" + i.ToString() + "--------");
            foreach(var res in resul){
                Console.WriteLine(res);
            }
            i++;
        }
        Console.ReadLine();
    }

    private static List<List<T>> splitListIntoSmallerLists<T>(List<T> i_bigList,int i_numberOfSmallerLists)
    {
        if (i_numberOfSmallerLists <= 0)
            throw new ArgumentOutOfRangeException("Illegal value of numberOfSmallLists");

        int normalizedSpreadRemainderCounter = 0;
        int normalizedSpreadNumber = 0;
        //e.g 7 /5 > 0 ==> output size is 5 , 2 /5 < 0 ==> output is 2          
        int minimumNumberOfPartsInEachSmallerList = i_bigList.Count / i_numberOfSmallerLists;                        
        int remainder = i_bigList.Count % i_numberOfSmallerLists;
        int outputSize = minimumNumberOfPartsInEachSmallerList > 0 ? i_numberOfSmallerLists : remainder;
        //In case remainder > 0 we want to spread the remainder equally between the others         
        if (remainder > 0)
        {
            if (minimumNumberOfPartsInEachSmallerList > 0)
            {
                normalizedSpreadNumber = (int)Math.Floor((double)i_numberOfSmallerLists / remainder);    
            }
            else
            {
                normalizedSpreadNumber = 1;
            }   
        }
        List<List<T>> retVal = new List<List<T>>(outputSize);
        int inputIndex = 0;            
        for (int i = 0; i < outputSize; ++i)
        {
            retVal.Add(new List<T>());
            if (minimumNumberOfPartsInEachSmallerList > 0)
            {
                retVal[i].AddRange(i_bigList.GetRange(inputIndex, minimumNumberOfPartsInEachSmallerList));
                inputIndex += minimumNumberOfPartsInEachSmallerList;
            }
            //If we have remainder take one from it, if our counter is equal to normalizedSpreadNumber.
            if (remainder > 0)
            {
                if (normalizedSpreadRemainderCounter == normalizedSpreadNumber-1)
                {
                    retVal[i].Add(i_bigList[inputIndex]);
                    remainder--;
                    inputIndex++;
                    normalizedSpreadRemainderCounter=0;
                }
                else
                {
                    normalizedSpreadRemainderCounter++;
                }
            }
        }
        return retVal;
    }      

}

0

এই অংশগুলিতে ক্রমটি খুব গুরুত্বপূর্ণ না হলে আপনি এটি চেষ্টা করতে পারেন:

int[] array = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = 3;

var result =
   array.Select((value, index) => new { Value = value, Index = index }).GroupBy(i => i.Index % n, i => i.Value);

// or
var result2 =
   from i in array.Select((value, index) => new { Value = value, Index = index })
   group i.Value by i.Index % n into g
   select g;

তবে এগুলিকে কোনও কারণে আইনুনামেবল <আইনিম্যারেবল <int>> এ কাস্ট করা যাবে না ...


এটা হতে পারে. সরাসরি
ingালাইয়ের

0

এটি আমার কোড, সুন্দর এবং সংক্ষিপ্ত।

 <Extension()> Public Function Chunk(Of T)(ByVal this As IList(Of T), ByVal size As Integer) As List(Of List(Of T))
     Dim result As New List(Of List(Of T))
     For i = 0 To CInt(Math.Ceiling(this.Count / size)) - 1
         result.Add(New List(Of T)(this.GetRange(i * size, Math.Min(size, this.Count - (i * size)))))
     Next
     Return result
 End Function

0

এটি আমার উপায়, আইটেমের তালিকা তৈরি এবং কলাম অনুসারে সারি ভাঙা

  int repat_count=4;

  arrItems.ForEach((x, i) => {
    if (i % repat_count == 0) 
        row = tbo.NewElement(el_tr, cls_min_height);
    var td = row.NewElement(el_td);
    td.innerHTML = x.Name;
  });

0

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

List<int> sequence = new List<int>();
for (int i = 0; i < 2000; i++)
{
     sequence.Add(i);
}
int splitIndex = 900;
List<List<int>> splitted = new List<List<int>>();
while (sequence.Count != 0)
{
    splitted.Add(sequence.Take(splitIndex).ToList() );
    sequence.RemoveRange(0, Math.Min(splitIndex, sequence.Count));
}

পরের বার চেষ্টা করুন: var nrs = গণনাকারী anRange (1,2000) .ToList ();
এমবিরোস

0

অংশের সংখ্যার পরিবর্তে আইটেমের সংখ্যার জন্য এখানে একটি সামান্য টুইট

public static class MiscExctensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int nbItems)
    {
        return (
            list
            .Select((o, n) => new { o, n })
            .GroupBy(g => (int)(g.n / nbItems))
            .Select(g => g.Select(x => x.o))
        );
    }
}

-1
int[] items = new int[] { 0,1,2,3,4,5,6,7,8,9, 10 };

int itemIndex = 0;
int groupSize = 2;
int nextGroup = groupSize;

var seqItems = from aItem in items
               group aItem by 
                            (itemIndex++ < nextGroup) 
                            ? 
                            nextGroup / groupSize
                            :
                            (nextGroup += groupSize) / groupSize
                            into itemGroup
               select itemGroup.AsEnumerable();

-1

এই থ্রেডটি জুড়ে এসেছে, এবং এখানে বেশিরভাগ সমাধানগুলিতে সংগ্রহে আইটেম যুক্ত করা, প্রতিটি পৃষ্ঠা কার্যকরভাবে ফেরত দেওয়ার আগে কার্যকরভাবে জড়িত। এটি দুটি কারণে খারাপ - প্রথমত যদি আপনার পৃষ্ঠাগুলি বড় হয় তবে পৃষ্ঠাটি পূরণ করার জন্য একটি মেমরির ওভারহেড রয়েছে, দ্বিতীয়ত এমন পুনরাবৃত্তি রয়েছে যা পূর্ববর্তী রেকর্ডগুলিকে অকার্যকর করে দেয় যখন আপনি পরের দিকে অগ্রসর হন (উদাহরণস্বরূপ যদি আপনি একটি গণনাকারী পদ্ধতির মধ্যে কোনও ডেটা রিডার গুটিয়ে রাখেন) ।

এই সমাধানটি অস্থায়ী সংগ্রহে আইটেমগুলি ক্যাশে করার কোনও প্রয়োজন এড়াতে দুটি নেস্টেড গণক পদ্ধতি ব্যবহার করে। যেহেতু বাহ্যিক এবং অভ্যন্তরীণ পুনরাবৃত্তিগুলি একই গণনাকারী লোকটিকে অনুসরণ করছে, তারা অগত্যা একই গণনাটি ভাগ করে নেবে, সুতরাং আপনি বর্তমান পৃষ্ঠাটি প্রক্রিয়াজাতকরণ শেষ না করা পর্যন্ত বাইরেরটিকে অগ্রসর না করা গুরুত্বপূর্ণ। এটি বলেছে, আপনি যদি বর্তমান পৃষ্ঠাটি দিয়ে সমস্ত পথে পুনরাবৃত্তি না করার সিদ্ধান্ত নেন, আপনি যখন পরবর্তী পৃষ্ঠায় যান তখন এই সমাধানটি স্বয়ংক্রিয়ভাবে পৃষ্ঠার সীমানায় ফিরে যেতে হবে।

using System.Collections.Generic;

public static class EnumerableExtensions
{
    /// <summary>
    /// Partitions an enumerable into individual pages of a specified size, still scanning the source enumerable just once
    /// </summary>
    /// <typeparam name="T">The element type</typeparam>
    /// <param name="enumerable">The source enumerable</param>
    /// <param name="pageSize">The number of elements to return in each page</param>
    /// <returns></returns>
    public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> enumerable, int pageSize)
    {
        var enumerator = enumerable.GetEnumerator();

        while (enumerator.MoveNext())
        {
            var indexWithinPage = new IntByRef { Value = 0 };

            yield return SubPartition(enumerator, pageSize, indexWithinPage);

            // Continue iterating through any remaining items in the page, to align with the start of the next page
            for (; indexWithinPage.Value < pageSize; indexWithinPage.Value++)
            {
                if (!enumerator.MoveNext())
                {
                    yield break;
                }
            }
        }
    }

    private static IEnumerable<T> SubPartition<T>(IEnumerator<T> enumerator, int pageSize, IntByRef index)
    {
        for (; index.Value < pageSize; index.Value++)
        {
            yield return enumerator.Current;

            if (!enumerator.MoveNext())
            {
                yield break;
            }
        }
    }

    private class IntByRef
    {
        public int Value { get; set; }
    }
}

এটি মোটেই কাজ করছে না! সর্বোত্তম সম্ভব এখানে স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি / 13709626/… ! মন্তব্য দেখুন।
স্যালিয়েন্টব্রেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.