একটি নির্দিষ্ট আকারের অংশগুলিতে একটি স্ট্রিং বিভক্ত করা


218

ধরুন আমার একটি স্ট্রিং ছিল:

string str = "1111222233334444"; 

আমি কীভাবে এই স্ট্রিংটিকে কিছু আকারের অংশে ভাঙ্গতে পারি?

উদাহরণস্বরূপ, এটি 4 টি আকারে ভাঙ্গা স্ট্রিংগুলি ফিরে আসবে:

"1111"
"2222"
"3333"
"4444"

18
যখন সি # এর স্ট্যান্ডার্ড স্ট্রিং ম্যানিপুলেশন ফাংশনগুলি কম প্রচেষ্টা এবং আরও গতির সাথে এটি করতে পারে তখন কেন লিনকিউ বা রেজেক্সস ব্যবহার করবেন? এছাড়াও, যদি স্ট্রিংটি দৈর্ঘ্যের একটি বিজোড় সংখ্যা হয়?
ইয়ান কেম্প

7
"আমি লুপগুলি এড়াতে চাই" - কেন?
মিচ গম 11

12
একটি সাধারণ লুপ ব্যবহার করা নিশ্চিতভাবেই যা সর্বোত্তম কর্মক্ষমতা দেয় gives
গুফা

4
nichesoftware.co.nz/blog/200909/linq-vs-loop-performance লিঙ্ক এবং একটি অ্যারের উপরে প্রকৃত লুপিংয়ের মধ্যে বেশ ভাল তুলনা। আমি সন্দেহ করি যে আপনি ম্যানুয়ালি লিখিত কোডের চেয়ে লিনাক আরও দ্রুত খুঁজে পাবেন কারণ এটি রান-টাইম প্রতিনিধিদের কল করতে থাকে যা অপ্টিমাইজ করা শক্ত। লিঙ্ক যদিও আরও মজাদার :)
অন্ধ

2
আপনি লিনকুই বা রেজিজেস ব্যবহার করছেন না কেন, লুপটি এখনও রয়েছে।
আন্তন টিখি

উত্তর:


247
static IEnumerable<string> Split(string str, int chunkSize)
{
    return Enumerable.Range(0, str.Length / chunkSize)
        .Select(i => str.Substring(i * chunkSize, chunkSize));
}

দয়া করে নোট করুন যে অতিরিক্ত কোডটি গ্রেফতার করে প্রান্তের কেসগুলি হ্যান্ডেল করার প্রয়োজন হতে পারে ( nullবা খালি ইনপুট স্ট্রিং chunkSize == 0, ইনপুট স্ট্রিংয়ের দৈর্ঘ্য দ্বারা ভাগ করা যায় না chunkSizeইত্যাদি)। মূল প্রশ্নটি এই প্রান্তের ক্ষেত্রে কোনও প্রয়োজনীয়তা নির্দিষ্ট করে না এবং বাস্তব জীবনে প্রয়োজনীয়তাগুলি পৃথক হতে পারে তাই তারা এই উত্তরের বাইরে নয়।


3
@ হ্যারি ভাল ক্যাচ! এটি স্ট্রিংয়ের কাউন্ট প্যারামিটারে ড্রপ-ইন টেরিনারি এক্সপ্রেশন দিয়ে প্রতিকার করা যেতে পারে। ভালো কিছু: (i * chunkSize + chunkSize <= str.Length) ? chunkSize : str.Length - i * chunkSize। একটি অতিরিক্ত সমস্যা হ'ল এই ফাংশনটি শূন্য হওয়ার জন্য অ্যাকাউন্ট করে না। এটি অন্য তিন এক্সপ্রেশনে পুরো রিটার্ন স্টেটমেন্ট মোড়কে দ্বারা নির্ধারিত করা যেতে পারে: (str != null) ? ... : Enumerable.Empty<String>();
ড্রয় স্পাইকস

7
এই ঘনিষ্ঠ ছিল, কিন্তু বিগত 30 upvoters অসদৃশ, আমি থেকে পরিসরের লুপ সংখ্যার সীমা পরিবর্তন করতে হয়েছিল str.Length / chunkSizeকরারdouble length = str.Length; double size = chunkSize; int count = (int)Math.Ceiling(length/size); return Enumerable.Range(0, count)...
ফাঁক

4
@ কনস্টান্টিনস্পিরিন কোডটি কাজ করে কিনা আমি সম্মত। এটি কেবলমাত্র সেই ক্ষেত্রেই হ্যান্ডল করে যেখানে স্ট্রিংটি চুনস সাইজের একাধিক, বাকী স্ট্রিংটি হারিয়ে যায়। দয়া করে সংশোধন করুন। এছাড়াও মনে রাখবেন যে লিনকিউ এবং এটি যাদু এমন কারও পক্ষে বোঝা তত সহজ নয় যে কেবল এই সমস্যার সমাধানটি দেখতে চায়। একজন ব্যক্তির এখন অবশ্যই Enumerable.Range () এবং .Select () ফাংশনগুলি কী তা বুঝতে হবে। আমি যুক্তি দেব না যে সি # /। নেট কোড লেখার জন্য আপনার এই ধারণাটি হওয়া উচিত কারণ এই ফাংশনগুলি বিসিএলে এখন বহু বছর ধরে রয়েছে।
কোডমনকিকিং

6
টপিক স্টার্টার মন্তব্য করেছেন StringLength % 4 will always be 0। যদি Linqবুঝতে সহজ হয় না তবে অন্যান্য উত্তরগুলি রয়েছে যা লুপ এবং ফলন ব্যবহার করে। যে কেউ তার সমাধান পছন্দ করতে পছন্দ করতে পারেন। আপনি উত্তর হিসাবে আপনার কোড পোস্ট করতে পারেন এবং লোকেরা আনন্দের সাথে এটির জন্য ভোট দেবে।
কনস্ট্যান্টিন স্পিরিন

3
Enumerable.Range (0, (str.Length + + chunkSize - 1) / chunkSize) .Select (ঝ => str.Substring (ঝ * chunkSize, Math.Min (str.Length - আমি chunkSize, chunkSize) *))
বাই স্টেন পেট্রোভ

135

ঘুঘু + কনস্ট্যাটিনের উত্তরগুলির সংমিশ্রণে ...

static IEnumerable<string> WholeChunks(string str, int chunkSize) {
    for (int i = 0; i < str.Length; i += chunkSize) 
        yield return str.Substring(i, chunkSize);
}

এটি এমন সমস্ত স্ট্রিংয়ের জন্য কাজ করবে যা পুরো সংখ্যায় বিভক্ত হতে পারে এবং অন্যথায় ব্যতিক্রম ছুঁড়ে ফেলবে।

আপনি যদি কোনও দৈর্ঘ্যের স্ট্রিং সমর্থন করতে চান তবে নীচের কোডটি ব্যবহার করতে পারেন:

static IEnumerable<string> ChunksUpto(string str, int maxChunkSize) {
    for (int i = 0; i < str.Length; i += maxChunkSize) 
        yield return str.Substring(i, Math.Min(maxChunkSize, str.Length-i));
}

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


4
নোডের মূল্য +1। কিন্ডা মাথায় পেরেক মেরেছিল। তিনি সিসিনেক্ট সিনট্যাক্সের সন্ধান করছেন এবং আপনি (সম্ভবত) আরও ভাল পারফরম্যান্স দিচ্ছেন।
কবুতর

7
এবং যদি আপনি এটি "স্ট্যাটিক ... অংশ (এই স্ট্রিং স্ট্র্ট, ইন্ট চঙ্কসাইজ) তৈরি করেন make" এমনকি এটির মধ্যে আপনি আরও একটি "নতুন" সি # -র বৈশিষ্ট্য রেখেছেন। তারপরে আপনি "1111222233334444" লিখতে পারেন hচানক (4)।
মার্টিনস্ট্যাটনার

1
@ মার্টিনস্টেটনার: এটি যদি একটি সাধারণ কাজ হয় তবে অবশ্যই এটি একটি শালীন ধারণা।
ইমন নের্বোন

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

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

56

লুপ কেন নয়? এখানে এমন কিছু যা এটি বেশ ভালভাবে করবে:

        string str = "111122223333444455";
        int chunkSize = 4;
        int stringLength = str.Length;
        for (int i = 0; i < stringLength ; i += chunkSize)
        {
            if (i + chunkSize > stringLength) chunkSize = stringLength  - i;
            Console.WriteLine(str.Substring(i, chunkSize));

        }
        Console.ReadLine();

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

বা মন্তব্যগুলিতে উল্লিখিত হিসাবে, আপনি জানেন যে এটি / 4 তখন

str = "1111222233334444";
for (int i = 0; i < stringLength; i += chunkSize) 
  {Console.WriteLine(str.Substring(i, chunkSize));} 

1
আপনি int chunkSize = 4লুপের বাইরে টানতে পারেন । এটি কেবলমাত্র চূড়ান্ত পাসেই সংশোধিত হবে।
জন Feminella

একটি সহজ এবং কার্যকর সমাধানের জন্য +1 - আমি এটির মতোই করতাম যদিও এর i += chunkSizeপরিবর্তে আমি ব্যবহার করতাম ।
ইয়ান কেম্প

সম্ভবত একটি ছোটখাটো বাচ্চা, তবে আপনার সম্ভবত str.Lengthলুপটি আউট এবং স্থানীয় ভেরিয়েবলের মধ্যেও টানতে হবে । সি # অপ্টিমাইজার হতে পারে অ্যারে দৈর্ঘ্যটি ইনলাইন করতে সক্ষম পারে, তবে আমি মনে করি লিখিত হিসাবে কোডটি প্রতিটি লুপে একটি পদ্ধতি কল করবে যা কার্যকর নয়, যেহেতু আকার strকখনই পরিবর্তন হয় না।
ড্যানিয়েল প্রাইডেন

@ ড্যানিয়েল, আপনার ধারণাটি সেখানে রাখুন। যদিও আমি নিশ্চিত নই যে রানটাইমের সময় এটি গণনা করা হবে না তবে এটি অন্য একটি প্রশ্ন;)
কবুতর

@ ড্যানিয়েল এটিতে ফিরে আসছেন, সম্পূর্ণরূপে নিশ্চিত যে এই অপটিমাইজেশনটি সংকলক দ্বারা বের করা হবে।
ঘুঘু

41

নিয়মিত এক্সপ্রেশন এবং লিনক ব্যবহার :

List<string> groups = (from Match m in Regex.Matches(str, @"\d{4}")
                       select m.Value).ToList();

আমি এটি আরও পাঠযোগ্য বলে মনে করি তবে এটি কেবল একটি ব্যক্তিগত মতামত। এটি ওয়ান-লাইনারও হতে পারে:)।


7
প্যাটার্নটি @ "\ d {1,4}" এ পরিবর্তন করুন এবং এটি কোনও স্ট্রিং দৈর্ঘ্যের জন্য কাজ করে। :)
Guffa

3
+1 যদিও এটি অন্যান্য সমাধানগুলির চেয়ে ধীরে ধীরে, এটি অবশ্যই খুব পঠনযোগ্য। ওপিতে অঙ্ক বা স্বেচ্ছাচারী অক্ষর প্রয়োজন কিনা তা আমার কাছে স্পষ্ট নয়; \dক্যারেক্টার ক্লাসটি এ-এর সাথে প্রতিস্থাপন করা .এবং নির্দিষ্ট করা সম্ভবত বুদ্ধিমানের কাজ হবে RegexOptions.Singleline
ইমন নারবোনে

2
বা কেবলমাত্র রেজেক্স। ম্যাচগুলি (গুলি, @ "\ d {1,4}")। নির্বাচন করুন (এম => মি। ভ্যালু)। আমি এই বিকল্প বাক্য গঠনটির বিন্দুটি পাই নি যা কেবলমাত্র আমরা কেবল এক্সটেনশন পদ্ধতি ব্যবহার করে যাচ্ছি তা হতাশ করতে সহায়তা করে।
দাগ

38

এটি @ কবুতরের সমাধানের উপর ভিত্তি করে তবে একটি এক্সটেনশন পদ্ধতি হিসাবে প্রয়োগ করা হয়েছে।

উপকারিতা:

  • সম্প্রসারণ পদ্ধতি
  • কর্নার কেস কভার করে
  • যে কোনও অক্ষরের সাথে স্ট্রিং বিভক্ত: সংখ্যা, অক্ষর, অন্যান্য প্রতীক

কোড

public static class EnumerableEx
{    
    public static IEnumerable<string> SplitBy(this string str, int chunkLength)
    {
        if (String.IsNullOrEmpty(str)) throw new ArgumentException();
        if (chunkLength < 1) throw new ArgumentException();

        for (int i = 0; i < str.Length; i += chunkLength)
        {
            if (chunkLength + i > str.Length)
                chunkLength = str.Length - i;

            yield return str.Substring(i, chunkLength);
        }
    }
}

ব্যবহার

var result = "bobjoecat".SplitBy(3); // bob, joe, cat

বংশবৃদ্ধির জন্য ইউনিট পরীক্ষা সরানো হয়েছে ( পূর্ববর্তী পুনর্বিবেচনাটি দেখুন )


আকর্ষণীয় সমাধান, তবে if (str.Length == 0) yield return String.Empty; else { for... }
ইনপুটটিতে

মানে, সাধারণ স্ট্রিং ringস্প্লিট খালি স্ট্রিংগুলি পরিচালনা করে; এটি একটি খালি স্ট্রিং এন্ট্রি দেয়।
নাইরেগডস

পার্শ্ব নোট: আপনার ব্যবহারের উদাহরণটি ভুল। আপনি কেবল IEnumerableঅ্যারেতে কাস্ট করতে পারবেন না , বিশেষত অন্তর্নিহিত নয়।
নাইয়ারগডস

আমি ব্যক্তিগতভাবে সেই পদ্ধতিটি কল করতে চাই Chunkify.. এটি আমার নয়, আমি নামটি কোথায় দেখেছি তা মনে নেই তবে এটি আমার কাছে খুব ভাল
লাগছিল

20

ওয়ান-লাইনারের জন্য এটি কেমন?

List<string> result = new List<string>(Regex.Split(target, @"(?<=\G.{4})", RegexOptions.Singleline));

এই রেজেক্সের সাথে শেষ অংশটি চারটি অক্ষরের চেয়ে কম কিনা তা বিবেচ্য নয়, কারণ এটি কেবল তার পিছনে থাকা অক্ষরগুলির দিকে নজর রাখে।

আমি নিশ্চিত যে এটি সর্বাধিক দক্ষ সমাধান নয়, তবে আমাকে কেবল সেখানে টস করতে হয়েছিল।


ক্ষেত্রে target.Lenght % ChunckSize == 0যে আয় একটি অতিরিক্ত খালি সারি যেমনList<string> result = new List<string>(Regex.Split("fooo", @"(?<=\G.{4})", RegexOptions.Singleline));
fubo

9

এটি সুন্দর নয় এবং এটি দ্রুত নয়, তবে এটি কাজ করে, এটি একটি ওয়ানলাইনার এবং এটি লিনকি:

List<string> a = text.Select((c, i) => new { Char = c, Index = i }).GroupBy(o => o.Index / 4).Select(g => new String(g.Select(o => o.Char).ToArray())).ToList();

এটি কি গ্যারান্টিযুক্ত যে গ্রুপপাই উপাদানগুলির ক্রম সংরক্ষণ করে?
কনস্ট্যান্টিন স্পিরিন

ToCharArrayযেহেতু অপ্রয়োজনীয় stringহয় IEnumerable<char>
জুলাই

8

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

using System;
using Extensions;

namespace TestCSharp
{
    class Program
    {
        static void Main(string[] args)
        {    
            string asciiStr = "This is a string.";
            string unicodeStr = "これは文字列です。";

            string[] array1 = asciiStr.Split(4);
            string[] array2 = asciiStr.Split(-4);

            string[] array3 = asciiStr.Split(7);
            string[] array4 = asciiStr.Split(-7);

            string[] array5 = unicodeStr.Split(5);
            string[] array6 = unicodeStr.Split(-5);
        }
    }
}

namespace Extensions
{
    public static class StringExtensions
    {
        /// <summary>Returns a string array that contains the substrings in this string that are seperated a given fixed length.</summary>
        /// <param name="s">This string object.</param>
        /// <param name="length">Size of each substring.
        ///     <para>CASE: length &gt; 0 , RESULT: String is split from left to right.</para>
        ///     <para>CASE: length == 0 , RESULT: String is returned as the only entry in the array.</para>
        ///     <para>CASE: length &lt; 0 , RESULT: String is split from right to left.</para>
        /// </param>
        /// <returns>String array that has been split into substrings of equal length.</returns>
        /// <example>
        ///     <code>
        ///         string s = "1234567890";
        ///         string[] a = s.Split(4); // a == { "1234", "5678", "90" }
        ///     </code>
        /// </example>            
        public static string[] Split(this string s, int length)
        {
            System.Globalization.StringInfo str = new System.Globalization.StringInfo(s);

            int lengthAbs = Math.Abs(length);

            if (str == null || str.LengthInTextElements == 0 || lengthAbs == 0 || str.LengthInTextElements <= lengthAbs)
                return new string[] { str.ToString() };

            string[] array = new string[(str.LengthInTextElements % lengthAbs == 0 ? str.LengthInTextElements / lengthAbs: (str.LengthInTextElements / lengthAbs) + 1)];

            if (length > 0)
                for (int iStr = 0, iArray = 0; iStr < str.LengthInTextElements && iArray < array.Length; iStr += lengthAbs, iArray++)
                    array[iArray] = str.SubstringByTextElements(iStr, (str.LengthInTextElements - iStr < lengthAbs ? str.LengthInTextElements - iStr : lengthAbs));
            else // if (length < 0)
                for (int iStr = str.LengthInTextElements - 1, iArray = array.Length - 1; iStr >= 0 && iArray >= 0; iStr -= lengthAbs, iArray--)
                    array[iArray] = str.SubstringByTextElements((iStr - lengthAbs < 0 ? 0 : iStr - lengthAbs + 1), (iStr - lengthAbs < 0 ? iStr + 1 : lengthAbs));

            return array;
        }
    }
}

এছাড়াও, এই কোডটি চালানোর ফলাফলগুলির জন্য এখানে একটি চিত্রের লিঙ্ক রয়েছে: http://i.imgur.com/16Iih.png


1
আমি এই কোডটি নিয়ে একটি সমস্যা লক্ষ্য করেছি। আপনার কাছে {str.ToString()}আপনার প্রথম If Statement শেষে। আপনি কি নিশ্চিতরূপে নিশ্চিত নন str.String? উপরের কোডটি নিয়ে আমার সমস্যা ছিল, পরিবর্তন হয়েছে এবং সবকিছুই কাজ করেছে।
gunr2171

@ gunr2171 দেখে মনে হচ্ছে যদি str == নাল হয়, তবে এই লাইনটি একটি নালরফেরানেক্সপশন দেয়।
জন জাবরোস্কি

5

এটি লিনকিউ বা এখানে ব্যবহৃত অন্যান্য পদ্ধতির ব্যবহারের চেয়ে অনেক দ্রুত এবং বেশি দক্ষ হওয়া উচিত।

public static IEnumerable<string> Splice(this string s, int spliceLength)
{
    if (s == null)
        throw new ArgumentNullException("s");
    if (spliceLength < 1)
        throw new ArgumentOutOfRangeException("spliceLength");

    if (s.Length == 0)
        yield break;
    var start = 0;
    for (var end = spliceLength; end < s.Length; end += spliceLength)
    {
        yield return s.Substring(start, spliceLength);
        start = end;
    }
    yield return s.Substring(start);
}

এই সৌন্দর্য এটা তাড়াতাড়ি পরীক্ষণ মত, কিন্তু এটা না। যতক্ষণ না আপনি গণনা করা শুরু করবেন ততক্ষণ আপনি ত্রুটি পাবেন না। আপনাকে আপনার ফাংশনটি দুটি ভাগে বিভক্ত করতে হবে, যেখানে প্রথম অংশটি যুক্তি যাচাই করে এবং তারপরে দ্বিতীয়, ব্যক্তিগত অংশের ফলাফল দেয় যা গণনা করে।
এরিক

4
public static IEnumerable<IEnumerable<T>> SplitEvery<T>(this IEnumerable<T> values, int n)
{
    var ls = values.Take(n);
    var rs = values.Skip(n);
    return ls.Any() ?
        Cons(ls, SplitEvery(rs, n)) : 
        Enumerable.Empty<IEnumerable<T>>();
}

public static IEnumerable<T> Cons<T>(T x, IEnumerable<T> xs)
{
    yield return x;
    foreach (var xi in xs)
        yield return xi;
}

4

আপনি জোন স্কিটের মোড়লিঙ্ক ব্যবহার করতে পারেন । ব্যাচ ব্যবহার করুন :

string str = "1111222233334444";
int chunkSize = 4;
var chunks = str.Batch(chunkSize).Select(r => new String(r.ToArray()));

এটি স্ট্রিংয়ের জন্য 4 টি অংশ ফিরে আসবে "1111222233334444"। স্ট্রিংয়ের দৈর্ঘ্য যদি অংশ আকারের চেয়ে কম বা সমান হয় Batchতবে স্ট্রিংটির একমাত্র উপাদান হিসাবে ফিরে আসবেIEnumerable<string>

আউটপুট জন্য:

foreach (var chunk in chunks)
{
    Console.WriteLine(chunk);
}

এবং এটি দেবে:

1111
2222
3333
4444

মোরলিনকিউ-র লেখকদের মধ্যে আমি জোনাথন স্কিটি দেখতে পাচ্ছি , তবে জন স্কিটি নেই । সুতরাং আপনি বোঝাতে চেয়েছেন জন স্কিট, নাকি? ;-)
Sнаđошƒаӽ

3
static IEnumerable<string> Split(string str, double chunkSize)
{
    return Enumerable.Range(0, (int) Math.Ceiling(str.Length/chunkSize))
       .Select(i => new string(str
           .Skip(i * (int)chunkSize)
           .Take((int)chunkSize)
           .ToArray()));
}

এবং অন্য পদ্ধতি:

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

public class Program
{
    public static void Main()
    {

        var x = "Hello World";
        foreach(var i in x.ChunkString(2)) Console.WriteLine(i);
    }
}

public static class Ext{
    public static IEnumerable<string> ChunkString(this string val, int chunkSize){
        return val.Select((x,i) => new {Index = i, Value = x})
                  .GroupBy(x => x.Index/chunkSize, x => x.Value)
                  .Select(x => string.Join("",x));
    }
}

3

ছয় বছর পরে o_O

শুধু কারণ

    public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
    {
        var count = (int) Math.Ceiling(str.Length/(double) chunkSize);
        Func<int, int> start = index => remainingInFront ? str.Length - (count - index)*chunkSize : index*chunkSize;
        Func<int, int> end = index => Math.Min(str.Length - Math.Max(start(index), 0), Math.Min(start(index) + chunkSize - Math.Max(start(index), 0), chunkSize));
        return Enumerable.Range(0, count).Select(i => str.Substring(Math.Max(start(i), 0),end(i)));
    }

অথবা

    private static Func<bool, int, int, int, int, int> start = (remainingInFront, length, count, index, size) =>
        remainingInFront ? length - (count - index) * size : index * size;

    private static Func<bool, int, int, int, int, int, int> end = (remainingInFront, length, count, index, size, start) =>
        Math.Min(length - Math.Max(start, 0), Math.Min(start + size - Math.Max(start, 0), size));

    public static IEnumerable<string> Split(this string str, int chunkSize, bool remainingInFront)
    {
        var count = (int)Math.Ceiling(str.Length / (double)chunkSize);
        return Enumerable.Range(0, count).Select(i => str.Substring(
            Math.Max(start(remainingInFront, str.Length, count, i, chunkSize), 0),
            end(remainingInFront, str.Length, count, i, chunkSize, start(remainingInFront, str.Length, count, i, chunkSize))
        ));
    }

আফাইক সমস্ত প্রান্তের মামলাগুলি পরিচালনা করা হয়।

Console.WriteLine(string.Join(" ", "abc".Split(2, false))); // ab c
Console.WriteLine(string.Join(" ", "abc".Split(2, true))); // a bc
Console.WriteLine(string.Join(" ", "a".Split(2, true))); // a
Console.WriteLine(string.Join(" ", "a".Split(2, false))); // a

"ইনপুট একটি খালি স্ট্রিং" প্রান্তের কেস সম্পর্কে কী বলা যায়? আমি প্রত্যাশা করতাম, স্প্লিটের মতোই, এন্ট্রি সম্বলিত একটি ফাঁকা স্ট্রিং সহ একটি আইমনামেবল ফিরিয়ে দেবে।
নাইয়ারগডস

3

সহজ এবং সংক্ষিপ্ত:

// this means match a space or not a space (anything) up to 4 characters
var lines = Regex.Matches(str, @"[\s\S]{0,4}").Cast<Match>().Select(x => x.Value);

কেন ব্যবহার .করবেন না ?
11

3
static IEnumerable<string> Split(string str, int chunkSize)
{
   IEnumerable<string> retVal = Enumerable.Range(0, str.Length / chunkSize)
        .Select(i => str.Substring(i * chunkSize, chunkSize))

   if (str.Length % chunkSize > 0)
        retVal = retVal.Append(str.Substring(str.Length / chunkSize * chunkSize, str.Length % chunkSize));

   return retVal;
}

এটি সঠিকভাবে ইনপুট স্ট্রিংয়ের দৈর্ঘ্য পরিচালনা করে চঙ্কসাইজে বিভাজ্য নয়।

দয়া করে নোট করুন যে অতিরিক্ত কোডটি গ্রেফতার হয়ে প্রান্তের কেসগুলি হ্যান্ডেল করার জন্য প্রয়োজন হতে পারে (নাল বা খালি ইনপুট স্ট্রিং, শঙ্কসাইজ == 0)।


2

যদি স্ট্রিংটি কাটা হচ্ছে তখন সমস্ত ইউনিকোড অক্ষরকে সমর্থন করা দরকার যদি একটি গুরুত্বপূর্ণ টিপ।

যদি স্ট্রিংটি আন্তর্জাতিক চরিত্রের মতো সমর্থন 𠀋করে তবে সিস্টেম.গ্লোবালাইজেশন.স্ট্রিংইনফো ক্লাস ব্যবহার করে স্ট্রিংটি বিভক্ত করুন। স্ট্রিংইনফো ব্যবহার করে আপনি পাঠ্য উপাদানগুলির সংখ্যার ভিত্তিতে স্ট্রিংটি বিভক্ত করতে পারেন।

string internationalString = '𠀋';

উপরের স্ট্রিংয়ের দৈর্ঘ্য 2 রয়েছে, কারণ String.Lengthসম্পত্তি এই উদাহরণে চর অবজেক্টগুলির সংখ্যা দেয়, ইউনিকোড অক্ষরের সংখ্যা নয়।


2

সেরা, সহজ এবং জেনারিক উত্তর :)।

    string originalString = "1111222233334444";
    List<string> test = new List<string>();
    int chunkSize = 4; // change 4 with the size of strings you want.
    for (int i = 0; i < originalString.Length; i = i + chunkSize)
    {
        if (originalString.Length - i >= chunkSize)
            test.Add(originalString.Substring(i, chunkSize));
        else
            test.Add(originalString.Substring(i,((originalString.Length - i))));
    }

শেষ লাইনে দৈর্ঘ্য গণনা করা অপ্রয়োজনীয়, কেবল ওভারলোডটি ব্যবহার করুন Substringযা দৈর্ঘ্যের প্যারামিটারের প্রয়োজন হয় না originalString.Substring(i)। এছাড়াও আপনি আপনার চেকের >পরিবর্তে ব্যবহার করতে পারেন >=
র্যাকিল হিলান

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

2

ব্যক্তিগতভাবে আমি আমার সমাধানটি পছন্দ করি :-)

এটি পরিচালনা করে:

  • স্ট্রিং দৈর্ঘ্য যা খণ্ড আকারের একাধিক।
  • স্ট্রিং দৈর্ঘ্য যা খণ্ড আকারের একাধিক নয়।
  • স্ট্রিং দৈর্ঘ্য যা খণ্ড আকারের চেয়ে ছোট।
  • নাল এবং খালি স্ট্রিং (একটি ব্যতিক্রম ছোঁড়ে)।
  • 1 টির চেয়ে ছোট আকারের আকার (একটি ব্যতিক্রম ছোঁড়ে)।

এটি একটি এক্সটেনশন পদ্ধতি হিসাবে প্রয়োগ করা হয়েছে এবং এটি হিসাব করে যে খণ্ডগুলির সংখ্যা আগে থেকে উত্পন্ন হতে চলেছে। এটি শেষ খণ্ডটি পরীক্ষা করে কারণ পাঠ্য দৈর্ঘ্যটি একাধিক না হলে এটি সংক্ষিপ্ত হওয়া দরকার। পরিষ্কার, সংক্ষিপ্ত, সহজে বোঝা যায় ... এবং কাজ করে!

    public static string[] Split(this string value, int chunkSize)
    {
        if (string.IsNullOrEmpty(value)) throw new ArgumentException("The string cannot be null.");
        if (chunkSize < 1) throw new ArgumentException("The chunk size should be equal or greater than one.");

        int remainder;
        int divResult = Math.DivRem(value.Length, chunkSize, out remainder);

        int numberOfChunks = remainder > 0 ? divResult + 1 : divResult;
        var result = new string[numberOfChunks];

        int i = 0;
        while (i < numberOfChunks - 1)
        {
            result[i] = value.Substring(i * chunkSize, chunkSize);
            i++;
        }

        int lastChunkSize = remainder > 0 ? remainder : chunkSize;
        result[i] = value.Substring(i * chunkSize, lastChunkSize);

        return result;
    }

2
List<string> SplitString(int chunk, string input)
{
    List<string> list = new List<string>();
    int cycles = input.Length / chunk;

    if (input.Length % chunk != 0)
        cycles++;

    for (int i = 0; i < cycles; i++)
    {
        try
        {
            list.Add(input.Substring(i * chunk, chunk));
        }
        catch
        {
            list.Add(input.Substring(i * chunk));
        }
    }
    return list;
}

1
আমার এই উত্তরটি অনেক পছন্দ হয়েছে তবে ব্যতিক্রমী ক্ষেত্রে ব্যতিক্রম হিসাবে চেষ্টা / ধরার পরিবর্তে আপনি যদি ((i + 1) * খণ্ড> = ইনপুট. দৈর্ঘ্য) ব্যবহার করেন তবে আপনার ব্যবহার করা উচিত।
নেলসন্ট্রুরান

2

আমি মনে করি এটি প্রত্যক্ষভাবে উত্তর:

public static IEnumerable<string> Split(this string str, int chunkSize)
    {
        if(string.IsNullOrEmpty(str) || chunkSize<1)
            throw new ArgumentException("String can not be null or empty and chunk size should be greater than zero.");
        var chunkCount = str.Length / chunkSize + (str.Length % chunkSize != 0 ? 1 : 0);
        for (var i = 0; i < chunkCount; i++)
        {
            var startIndex = i * chunkSize;
            if (startIndex + chunkSize >= str.Length)
                yield return str.Substring(startIndex);
            else
                yield return str.Substring(startIndex, chunkSize);
        }
    }

এবং এটি প্রান্তের মামলাগুলি অন্তর্ভুক্ত করে।


2

আমি জানি প্রশ্নটি বহু বছরের পুরনো, তবে এখানে একটি আরএক্স বাস্তবায়ন। এটি length % chunkSize != 0বাক্সের বাইরে সমস্যাটি পরিচালনা করে :

   public static IEnumerable<string> Chunkify(this string input, int size)
        {
            if(size < 1)
                throw new ArgumentException("size must be greater than 0");

            return input.ToCharArray()
                .ToObservable()
                .Buffer(size)            
                .Select(x => new string(x.ToArray()))
                .ToEnumerable();
        }

1

আমি জোওোর সমাধানটি কিছুটা বাড়িয়েছি build আমি আলাদাভাবে যা করেছি তা আমার পদ্ধতিতে আপনি নির্দিষ্ট করে বলতে পারবেন আপনি কী বাকী অক্ষর দিয়ে অ্যারে ফিরিয়ে দিতে চান বা শেষ অক্ষরগুলি আপনার প্রয়োজনীয় অংশের দৈর্ঘ্যের সাথে মেলে না যদি আপনি তাদের কেটে ফেলতে চান কিনা, আমি মনে করি এটি বেশ নমনীয় এবং কোড মোটামুটি সোজা এগিয়ে:

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace SplitFunction
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "hello, how are you doing today?";
            string[] chunks = SplitIntoChunks(text, 3,false);
            if (chunks != null)
            {
                chunks.ToList().ForEach(e => Console.WriteLine(e));
            }

            Console.ReadKey();
        }

        private static string[] SplitIntoChunks(string text, int chunkSize, bool truncateRemaining)
        {
            string chunk = chunkSize.ToString(); 
            string pattern = truncateRemaining ? ".{" + chunk + "}" : ".{1," + chunk + "}";

            string[] chunks = null;
            if (chunkSize > 0 && !String.IsNullOrEmpty(text))
                chunks = (from Match m in Regex.Matches(text,pattern)select m.Value).ToArray(); 

            return chunks;
        }     
    }
}

1
    public static List<string> SplitByMaxLength(this string str)
    {
        List<string> splitString = new List<string>();

        for (int index = 0; index < str.Length; index += MaxLength)
        {
            splitString.Add(str.Substring(index, Math.Min(MaxLength, str.Length - index)));
        }

        return splitString;
    }

আপনি, হ্যাঁ, ম্যাক্সলেংথ প্যারামিটারটি ভুলে গেছেন।
নায়ারগডস

1

অংশগুলি ফিরে আসতে সামান্য পরিবর্তিত হয়েছে যার আকার চুনসাইজের সমান নয়

public static IEnumerable<string> Split(this string str, int chunkSize)
    {
        var splits = new List<string>();
        if (str.Length < chunkSize) { chunkSize = str.Length; }
        splits.AddRange(Enumerable.Range(0, str.Length / chunkSize).Select(i => str.Substring(i * chunkSize, chunkSize)));
        splits.Add(str.Length % chunkSize > 0 ? str.Substring((str.Length / chunkSize) * chunkSize, str.Length - ((str.Length / chunkSize) * chunkSize)) : string.Empty);
        return (IEnumerable<string>)splits;
    }

না নিশ্চিত আমি ব্যাক ঢালাই ব্যবহার দেখতে যে Listথেকে IEnumerable; যা করা হয় তা হ'ল তালিকা-নির্দিষ্ট ফাংশনগুলি আপনি ব্যবহার করতে চাইতে পারেন h কেবলমাত্র ফিরে আসার জন্য কোনও খারাপ দিক নেই List
নাইয়ারগডস

1

কে আমাকে এ দিয়েছে তা আমি মনে করতে পারি না তবে এটি দুর্দান্ত কাজ করে। আমি অসংখ্য ধরণের গ্রুপে বিভক্ত করার জন্য বেশ কয়েকটি উপায় পরীক্ষা করেছি tested ব্যবহার ঠিক এই রকম হবে ...

List<string> Divided = Source3.Chunk(24).Select(Piece => string.Concat<char>(Piece)).ToList();

এক্সটেনশন কোডটি দেখতে এমন হবে ...

#region Chunk Logic
private class ChunkedEnumerable<T> : IEnumerable<T>
{
    class ChildEnumerator : IEnumerator<T>
    {
        ChunkedEnumerable<T> parent;
        int position;
        bool done = false;
        T current;


        public ChildEnumerator(ChunkedEnumerable<T> parent)
        {
            this.parent = parent;
            position = -1;
            parent.wrapper.AddRef();
        }

        public T Current
        {
            get
            {
                if (position == -1 || done)
                {
                    throw new InvalidOperationException();
                }
                return current;

            }
        }

        public void Dispose()
        {
            if (!done)
            {
                done = true;
                parent.wrapper.RemoveRef();
            }
        }

        object System.Collections.IEnumerator.Current
        {
            get { return Current; }
        }

        public bool MoveNext()
        {
            position++;

            if (position + 1 > parent.chunkSize)
            {
                done = true;
            }

            if (!done)
            {
                done = !parent.wrapper.Get(position + parent.start, out current);
            }

            return !done;

        }

        public void Reset()
        {
            // per http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx
            throw new NotSupportedException();
        }
    }

    EnumeratorWrapper<T> wrapper;
    int chunkSize;
    int start;

    public ChunkedEnumerable(EnumeratorWrapper<T> wrapper, int chunkSize, int start)
    {
        this.wrapper = wrapper;
        this.chunkSize = chunkSize;
        this.start = start;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return new ChildEnumerator(this);
    }

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

}
private class EnumeratorWrapper<T>
{
    public EnumeratorWrapper(IEnumerable<T> source)
    {
        SourceEumerable = source;
    }
    IEnumerable<T> SourceEumerable { get; set; }

    Enumeration currentEnumeration;

    class Enumeration
    {
        public IEnumerator<T> Source { get; set; }
        public int Position { get; set; }
        public bool AtEnd { get; set; }
    }

    public bool Get(int pos, out T item)
    {

        if (currentEnumeration != null && currentEnumeration.Position > pos)
        {
            currentEnumeration.Source.Dispose();
            currentEnumeration = null;
        }

        if (currentEnumeration == null)
        {
            currentEnumeration = new Enumeration { Position = -1, Source = SourceEumerable.GetEnumerator(), AtEnd = false };
        }

        item = default(T);
        if (currentEnumeration.AtEnd)
        {
            return false;
        }

        while (currentEnumeration.Position < pos)
        {
            currentEnumeration.AtEnd = !currentEnumeration.Source.MoveNext();
            currentEnumeration.Position++;

            if (currentEnumeration.AtEnd)
            {
                return false;
            }

        }

        item = currentEnumeration.Source.Current;

        return true;
    }

    int refs = 0;

    // needed for dispose semantics 
    public void AddRef()
    {
        refs++;
    }

    public void RemoveRef()
    {
        refs--;
        if (refs == 0 && currentEnumeration != null)
        {
            var copy = currentEnumeration;
            currentEnumeration = null;
            copy.Source.Dispose();
        }
    }
}
/// <summary>Speed Checked.  Works Great!</summary>
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> source, int chunksize)
{
    if (chunksize < 1) throw new InvalidOperationException();

    var wrapper = new EnumeratorWrapper<T>(source);

    int currentPos = 0;
    T ignore;
    try
    {
        wrapper.AddRef();
        while (wrapper.Get(currentPos, out ignore))
        {
            yield return new ChunkedEnumerable<T>(wrapper, chunksize, currentPos);
            currentPos += chunksize;
        }
    }
    finally
    {
        wrapper.RemoveRef();
    }
}
#endregion

1
class StringHelper
{
    static void Main(string[] args)
    {
        string str = "Hi my name is vikas bansal and my email id is bansal.vks@gmail.com";
        int offSet = 10;

        List<string> chunks = chunkMyStr(str, offSet);

        Console.Read();
    }

    static List<string> chunkMyStr(string str, int offSet)
    {


        List<string> resultChunks = new List<string>();

        for (int i = 0; i < str.Length; i += offSet)
        {
            string temp = str.Substring(i, (str.Length - i) > offSet ? offSet : (str.Length - i));
            Console.WriteLine(temp);
            resultChunks.Add(temp);


        }

        return resultChunks;
    }
}

আপনি আপনার কোডটি কিছুটা উন্নত করতে পারেন: বর্ধিত অভিব্যক্তিটিকে i += offSetআপনার forঅভিব্যক্তিতে স্থানান্তর করুন ।
জিমিওলো

1

সংশোধিত (এখন এটি কোনও নাল stringএবং কোনও ইতিবাচক গ্রহণ করে chunkSize) কনস্ট্যান্টিন স্পিরিনের সমাধান:

public static IEnumerable<String> Split(String value, int chunkSize) {
  if (null == value)
    throw new ArgumentNullException("value");
  else if (chunkSize <= 0)
    throw new ArgumentOutOfRangeException("chunkSize", "Chunk size should be positive");

  return Enumerable
    .Range(0, value.Length / chunkSize + ((value.Length % chunkSize) == 0 ? 0 : 1))
    .Select(index => (index + 1) * chunkSize < value.Length 
      ? value.Substring(index * chunkSize, chunkSize)
      : value.Substring(index * chunkSize));
}

পরীক্ষা:

  String source = @"ABCDEF";

  // "ABCD,EF"
  String test1 = String.Join(",", Split(source, 4));
  // "AB,CD,EF"
  String test2 = String.Join(",", Split(source, 2));
  // "ABCDEF"
  String test3 = String.Join(",", Split(source, 123));

1
static List<string> GetChunks(string value, int chunkLength)
{
    var res = new List<string>();
    int count = (value.Length / chunkLength) + (value.Length % chunkLength > 0 ? 1 : 0);
    Enumerable.Range(0, count).ToList().ForEach(f => res.Add(value.Skip(f * chunkLength).Take(chunkLength).Select(z => z.ToString()).Aggregate((a,b) => a+b)));
    return res;
}

ডেমো


এইটি স্ট্রিংয়ের অবশিষ্ট অংশটি রাখে (বিভক্ত হওয়ার পরে) এমনকি এটি "চুঙ্কলিংঘ্ট" এর চেয়েও ছোট, ধন্যবাদ
জেসন লোকি স্মিথ

0

ব্যবহারের কয়েকটি নমুনার পাশাপাশি অন্যান্য পোস্টারগুলির উত্তরগুলির আশেপাশে:

public static string FormatSortCode(string sortCode)
{
    return ChunkString(sortCode, 2, "-");
}
public static string FormatIBAN(string iban)
{
    return ChunkString(iban, 4, "&nbsp;&nbsp;");
}

private static string ChunkString(string str, int chunkSize, string separator)
{
    var b = new StringBuilder();
    var stringLength = str.Length;
    for (var i = 0; i < stringLength; i += chunkSize)
    {
        if (i + chunkSize > stringLength) chunkSize = stringLength - i;
        b.Append(str.Substring(i, chunkSize));
        if (i+chunkSize != stringLength)
            b.Append(separator);
    }
    return b.ToString();
}

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