2009-10-27 8 views
10

शायद एक बुनियादी सवाल है लेकिन हमें बताएं कि मेरे पास एक स्ट्रिंग है जो 2000 वर्ण लंबा है, मुझे इस स्ट्रिंग को अधिकतम 512 वर्णों में विभाजित करने की आवश्यकता है।512 चार हिस्सों में स्प्लिट स्ट्रिंग

क्या ऐसा करने के लिए एक लूप या ऐसा कोई अच्छा तरीका है?

+0

क्या आप वाकई 512 ** चार ** मात्रा की जरूरत है? क्योंकि यह 512 ** बाइट्स से अलग है ** जो एक अधिक आम बाधा है। –

+1

@ हेंक: दूसरी तरफ, * बाइट्स * के आधार पर विभाजित * पाठ * भाग में अजीब होगा - परिणाम एन्कोडिंग पर निर्भर होंगे। –

+0

जॉन, हां, पाठ को फिर से इकट्ठा करते समय एक आम समस्या है। लेकिन कुछ I/O चैनल 512 बाइट ब्लॉक में काम करते हैं। –

उत्तर

20

कुछ इस तरह:

private IList<string> SplitIntoChunks(string text, int chunkSize) 
{ 
    List<string> chunks = new List<string>(); 
    int offset = 0; 
    while (offset < text.Length) 
    { 
     int size = Math.Min(chunkSize, text.Length - offset); 
     chunks.Add(text.Substring(offset, size)); 
     offset += size; 
    } 
    return chunks; 
} 

या बस से अधिक पुनरावृति करने के लिए:

private IEnumerable<string> SplitIntoChunks(string text, int chunkSize) 
{ 
    int offset = 0; 
    while (offset < text.Length) 
    { 
     int size = Math.Min(chunkSize, text.Length - offset); 
     yield return text.Substring(offset, size); 
     offset += size; 
    } 
} 

ध्यान दें कि यह UTF-16 कोड इकाइयों के टुकड़ों में विभाजित करता है, जो काफी तेज के समान नहीं है यूनिकोड कोड बिंदुओं के टुकड़ों में, जो बदले में ग्लिफ के हिस्सों में विभाजित होने जैसा नहीं हो सकता है।

+0

जॉन आपको दोषी ठहराएं मुझे इसे हराया, और मैंने आपके कार्यान्वयन का भी उपयोग किया ... –

+0

मैंने इस से बहुत कुछ सीखा। स्वीकार करें और +1। बहुत अच्छा! – janhartmann

+0

यह एल्गोरिदम (और यूनिकोड के साथ इसकी _compatibility_) पर भी कोड समीक्षा पर चर्चा की गई है: [एक स्ट्रिंग को एक ही लंबाई के भाग में विभाजित करें] (http://codereview.stackexchange.com/a/111925/13424)। –

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

स्रोत: Splitting a string into chunks of a certain size

+0

+1, प्रदर्शन और पठनीयता के लिए -1 – Foxfire

+9

इस मामले में अंतिम खंड प्रदान करने में विफल रहता है। –

-1

कुछ पसंद है?

Calculate eachLength = StringLength/WantedCharLength 
Then for (int i = 0; i < StringLength; i += eachLength) 
SubString (i, eachLength); 
+2

क्या यह सी # है .... – Abel

1

मुझे लगता है कि string प्रकार लागू करता है IEnumerable<char> जॉन की समाधान का एक और अधिक LINQified संस्करण, तथ्य पर आधारित प्रदान करने के लिए हिम्मत देगा:

private IList<string> SplitIntoChunks(string text, int chunkSize) 
{ 
    var chunks = new List<string>(); 
    int offset = 0; 
    while(offset < text.Length) { 
     chunks.Add(new string(text.Skip(offset).Take(chunkSize).ToArray())); 
     offset += chunkSize; 
    } 
    return chunks; 
} 
+1

मैंने इस पर विचार किया - विशेष रूप से मोरिलक्यू इस तरह की चीज़ के लिए एक अच्छी विभाजन विधि प्रदान करता है। हालांकि, इसकी दक्षता बिल्कुल भयानक होगी :( –

+0

यह जानना अच्छा है कि, क्योंकि मैं सबकुछ के लिए LINQ का उपयोग करता हूं ... – Konamiman

+0

बीटीडब्ल्यू स्ट्रिंग, "छोड़ने" के लिए एक एक्सटेंशन विधि नहीं है, आपको करना होगा ToCharArray पहले। –

3

जॉन की कार्यान्वयन और उपज कीवर्ड का उपयोग।

IEnumerable<string> Chunks(string text, int chunkSize) 
{ 
    for (int offset = 0; offset < text.Length; offset += chunkSize) 
    { 
     int size = Math.Min(chunkSize, text.Length - offset); 
     yield return text.Substring(offset, size); 
    } 
} 
+0

मेरे बनाम बनाम के लिए दिलचस्प उपयोग ... मैं हूँ यह तय करने की कोशिश कर रहा है कि पढ़ने के लिए कौन सा आसान है। आपको अंत में उपज ब्रेक की आवश्यकता नहीं है, बीटीडब्ल्यू। –

+0

मैंने अनावश्यक उपज ब्रेक को ठीक करने के लिए स्वतंत्रता ली क्योंकि @Jon ने –

+0

का उल्लेख किया है, @LouisRhys :) –

3

हालांकि इस सवाल तब तक स्वीकृत उत्तर नहीं है, यहाँ नियमित अभिव्यक्ति की मदद से एक लघु संस्करण है। पुरी इसे पसंद नहीं कर सकते (समझदारी से) लेकिन जब आपको त्वरित समाधान की आवश्यकता होती है और आप regexes के साथ काम कर रहे हैं, तो यह हो सकता है। प्रदर्शन अपेक्षाकृत अच्छा है, आश्चर्यजनक रूप से:

string [] split = Regex.Split(yourString, @"(?<=\G.{512})"); 

यह क्या करता है? नकारात्मक दिखने वाला पिछला और \G के साथ अंतिम स्थिति को याद रखना। यह अंतिम बिट भी पकड़ लेगा, भले ही यह 512 तक विभाजित न हो।

+0

तत्काल विंडो में लंबे तारों का निरीक्षण करने के लिए उपयोगी। – Dialecticus

+1

क्यों नहीं? यह छोटा, तेज़ और स्पष्ट है (यदि आप regexes जानते हैं, व्यक्तिगत रूप से मुझे इसे पढ़ना था और इसे 3 बार परीक्षण करना था)। अच्छा संस्करण! –

1

अधिकांश उत्तर में एक ही दोष हो सकता है। एक खाली पाठ को देखते हुए वे कुछ भी नहीं कमाएंगे। हम (i) कम से कम उस रिक्त स्ट्रिंग को वापस पाने की उम्मीद करते हैं (स्ट्रिंग में नहीं होने वाले चार पर एक विभाजन के समान व्यवहार, जो एक आइटम वापस देगा:

इसलिए हमें कम से कम एक बार लूप करना चाहिए हर समय (जॉन की कोड के आधार पर):

IEnumerable<string> SplitIntoChunks (string text, int chunkSize) 
{ 
    int offset = 0; 
    do 
    { 
     int size = Math.Min (chunkSize, text.Length - offset); 
     yield return text.Substring (offset, size); 
     offset += size; 
    } while (offset < text.Length); 
} 

या के लिए एक का उपयोग कर (संपादित: एक छोटे से इस के साथ और अधिक कर रही के बाद, मैं मामले chunkSize पाठ से अधिक को संभालने के लिए एक बेहतर रास्ता मिल गया):

IEnumerable<string> SplitIntoChunks (string text, int chunkSize) 
{ 
    if (text.Length <= chunkSize) 
     yield return text; 
    else 
    { 
     var chunkCount = text.Length/chunkSize; 
     var remainingSize = text.Length % chunkSize; 

     for (var offset = 0; offset < chunkCount; ++offset) 
      yield return text.Substring (offset * chunkSize, chunkSize); 

     // yield remaining text if any 
     if (remainingSize != 0) 
      yield return text.Substring (chunkCount * chunkSize, remainingSize); 
    } 
} 

भी/करते हैं के साथ इस्तेमाल किया जा सकता है कि, जबकि पाश;)

0

जेनेरिक विस्तार विधि:

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

public static class IEnumerableExtensions 
{ 
    public static IEnumerable<IEnumerable<T>> SplitToChunks<T> (this IEnumerable<T> coll, int chunkSize) 
    { 
    int skipCount = 0; 
    while (coll.Skip (skipCount).Take (chunkSize) is IEnumerable<T> part && part.Any()) 
    { 
     skipCount += chunkSize; 
     yield return part; 
    } 
    } 
} 

class Program 
{ 
    static void Main (string[] args) 
    { 
    var col = Enumerable.Range(1,1<<10); 
    var chunks = col.SplitToChunks(8); 

    foreach (var c in chunks.Take (200)) 
    { 
     Console.WriteLine (string.Join (" ", c.Select (n => n.ToString ("X4")))); 
    } 

    Console.WriteLine(); 
    Console.WriteLine(); 

    "Split this text into parts that are fifteen characters in length, surrounding each part with single quotes and output each into the console on seperate lines." 
     .SplitToChunks (15) 
     .Select(p => $"'{string.Concat(p)}'") 
     .ToList() 
     .ForEach (p => Console.WriteLine (p)); 

    Console.ReadLine(); 
    } 
} 
संबंधित मुद्दे