"Thequickbrownfoxjumps"
जावा में समान आकार के सब्सट्रिंग के लिए स्ट्रिंग को कैसे विभाजित किया जाए । उदाहरण के लिए। "Thequickbrownfoxjumps"
4 के बराबर आकार आउटपुट देना चाहिए।
["Theq","uick","brow","nfox","jump","s"]
इसी तरह का प्रश्न:
"Thequickbrownfoxjumps"
जावा में समान आकार के सब्सट्रिंग के लिए स्ट्रिंग को कैसे विभाजित किया जाए । उदाहरण के लिए। "Thequickbrownfoxjumps"
4 के बराबर आकार आउटपुट देना चाहिए।
["Theq","uick","brow","nfox","jump","s"]
इसी तरह का प्रश्न:
जवाबों:
यहाँ रेगेक्स वन-लाइनर संस्करण है:
System.out.println(Arrays.toString(
"Thequickbrownfoxjumps".split("(?<=\\G.{4})")
));
\G
एक शून्य-चौड़ाई का दावा है जो उस स्थिति से मेल खाता है जहां पिछला मैच समाप्त हुआ था। यदि कोई पिछला मैच नहीं था , तो यह इनपुट की शुरुआत से मेल खाता है, जैसा कि\A
। पिछले मैच के अंत से चार अक्षरों के साथ स्थिति को देखने वाला संलग्नक मेल खाता है।
दोनों दिखावे और \G
उन्नत regex विशेषताएं हैं, सभी स्वादों द्वारा समर्थित नहीं हैं। इसके अलावा, \G
इसका समर्थन करने वाले स्वादों पर लगातार लागू नहीं किया जाता है। यह ट्रिक Java (पर्ल), .NET और JGSoft में (उदाहरण के लिए) काम करेगी, लेकिन इसमें नहीं PHP (PCRE), रूबी 1.9+ या टेक्स्टमैट (ओनिगुरुमा) में नहीं। जावास्क्रिप्ट का /y
(चिपचिपा झंडा) उतना लचीला नहीं है \G
, और इस तरह भी इस्तेमाल नहीं किया जा सकता है, भले ही जेएस ने समर्थन किया हो।
मुझे यह उल्लेख करना चाहिए कि यदि आपके पास अन्य विकल्प हैं, तो मैं जरूरी नहीं कि इस समाधान की सिफारिश करूं । अन्य उत्तरों में गैर-रेगेक्स समाधान लंबे समय तक हो सकते हैं, लेकिन वे स्वयं-दस्तावेज भी हैं; यह ठीक इसके विपरीत है है। ;)
इसके अलावा, यह एंड्रॉइड में काम नहीं करता है, जो \G
लुकबाइंड के उपयोग का समर्थन नहीं करता है ।
String.substring()
रेगेक्स के बजाय, कोड की कुछ अतिरिक्त पंक्तियों की आवश्यकता होने पर, 5x के क्रम पर कहीं तेज गति से चलेगा ...
(?s)
को रेगेक्स में एक उपसर्ग की आवश्यकता होती है (?s)(?<=\\G.{4})
:।
java.util.regex.PatternSyntaxException: Look-behind pattern matches must have a bounded maximum length
ठीक है, साधारण अंकगणित और स्ट्रिंग ऑपरेशन के साथ ऐसा करना काफी आसान है:
public static List<String> splitEqually(String text, int size) {
// Give the list the right capacity to start with. You could use an array
// instead if you wanted.
List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);
for (int start = 0; start < text.length(); start += size) {
ret.add(text.substring(start, Math.min(text.length(), start + size)));
}
return ret;
}
मुझे नहीं लगता कि यह वास्तव में इस के लिए एक regex का उपयोग करने के लायक है।
संपादित करें: एक regex का उपयोग नहीं करने के लिए मेरा तर्क:
Splitter.fixedLength(4)
सुझाता हूँ कि अमरूद का सुझाव सीनियर द्वारा दिया गया है।
Google अमरूद के साथ यह बहुत आसान है :
for(final String token :
Splitter
.fixedLength(4)
.split("Thequickbrownfoxjumps")){
System.out.println(token);
}
आउटपुट:
Theq
uick
brow
nfox
jump
s
या यदि आपको एक सरणी के रूप में परिणाम की आवश्यकता है, तो आप इस कोड का उपयोग कर सकते हैं:
String[] tokens =
Iterables.toArray(
Splitter
.fixedLength(4)
.split("Thequickbrownfoxjumps"),
String.class
);
संदर्भ:
नोट: फाड़नेवाला निर्माण ऊपर इनलाइन दिखाया गया है, लेकिन चूंकि स्प्लिटर्स अपरिवर्तनीय और पुन: प्रयोज्य हैं, इसलिए उन्हें स्थिरांक में संग्रहीत करना एक अच्छा अभ्यास है:
private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4);
// more code
for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){
System.out.println(token);
}
String.join(separator, arrayOrCollection)
यदि आप Google के अमरूद के सामान्य-उद्देश्य वाले पुस्तकालयों का उपयोग कर रहे हैं (और काफी ईमानदारी से, कोई भी नया जावा प्रोजेक्ट शायद होना चाहिए), तो यह फाड़नेवाला वर्ग के साथ तुच्छ है :
for (String substring : Splitter.fixedLength(4).split(inputString)) {
doSomethingWith(substring);
}
और यह बात है । के रूप में आसान!
public static String[] split(String src, int len) {
String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)];
for (int i=0; i<result.length; i++)
result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len));
return result;
}
src.length()
और len
दोनों कर रहे हैं int
रों हैं तो आपके कॉल ceiling
को पूरा नहीं कर रहा है कि तुम क्या चाहते हैं - बाहर की जाँच कैसे अन्य प्रतिक्रियाओं में से कुछ कर रहे हैं: (src.length () + लेन - 1) / लेन
public String[] splitInParts(String s, int partLength)
{
int len = s.length();
// Number of parts
int nparts = (len + partLength - 1) / partLength;
String parts[] = new String[nparts];
// Break into parts
int offset= 0;
int i = 0;
while (i < nparts)
{
parts[i] = s.substring(offset, Math.min(offset + partLength, len));
offset += partLength;
i++;
}
return parts;
}
for
छोरों के खिलाफ कुछ है?
for
लूप वास्तव में इस के लिए एक अधिक 'प्राकृतिक' पसंद का उपयोग है :-) इसे इंगित करने के लिए धन्यवाद।
आप (अपवादों को संभालते हुए) या अपाचे लैंग कॉमन्सsubstring
से उपयोग कर सकते हैं (यह आपके लिए अपवादों को संभालता है)String.class
static String substring(String str, int start, int end)
इसे एक लूप के अंदर रखें और आप जाने के लिए अच्छे हैं।
substring
मानक String
वर्ग में विधि के साथ क्या गलत है ?
मैं इस सरल समाधान के बजाय:
String content = "Thequickbrownfoxjumps";
while(content.length() > 4) {
System.out.println(content.substring(0, 4));
content = content.substring(4);
}
System.out.println(content);
substring
कार्यान्वयन जावा 7, 2012 के मध्य में अद्यतन 6, जब साथ बदला offset
और count
क्षेत्रों से हटा दिया गया String
वर्ग। तो substring
इस उत्तर के बनने से बहुत पहले ही रेखीय में बदल गया। उदाहरण के लिए एक छोटे से तार के लिए, यह अभी भी काफी तेजी से और लंबे समय तक तार के लिए चलता है ... अच्छी तरह से यह कार्य शायद ही कभी अभ्यास में होता है।
यहाँ Java8 धाराओं का उपयोग करते हुए एक लाइनर कार्यान्वयन है:
String input = "Thequickbrownfoxjumps";
final AtomicInteger atomicInteger = new AtomicInteger(0);
Collection<String> result = input.chars()
.mapToObj(c -> String.valueOf((char)c) )
.collect(Collectors.groupingBy(c -> atomicInteger.getAndIncrement() / 4
,Collectors.joining()))
.values();
यह निम्नलिखित आउटपुट देता है:
[Theq, uick, brow, nfox, jump, s]
String[] result = IntStream.range(0, (input.length()+3)/4) .mapToObj(i -> input.substring(i *= 4, Math.min(i + 4, input.length()))) .toArray(String[]::new);
यहां एक-लाइनर संस्करण है जो स्लाइस की शुरुआत के सूचकांक को निर्धारित करने के लिए जावा 8 इंटस्ट्रीम का उपयोग करता है :
String x = "Thequickbrownfoxjumps";
String[] result = IntStream
.iterate(0, i -> i + 4)
.limit((int) Math.ceil(x.length() / 4.0))
.mapToObj(i ->
x.substring(i, Math.min(i + 4, x.length())
)
.toArray(String[]::new);
यदि आप स्ट्रिंग को समान रूप से पीछे की ओर विभाजित करना चाहते हैं, अर्थात दाएं से बाएं, उदाहरण के 1010001111
लिए [10, 1000, 1111]
, यहाँ विभाजित करने के लिए , कोड:
/**
* @param s the string to be split
* @param subLen length of the equal-length substrings.
* @param backwards true if the splitting is from right to left, false otherwise
* @return an array of equal-length substrings
* @throws ArithmeticException: / by zero when subLen == 0
*/
public static String[] split(String s, int subLen, boolean backwards) {
assert s != null;
int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1;
String[] strs = new String[groups];
if (backwards) {
for (int i = 0; i < groups; i++) {
int beginIndex = s.length() - subLen * (i + 1);
int endIndex = beginIndex + subLen;
if (beginIndex < 0)
beginIndex = 0;
strs[groups - i - 1] = s.substring(beginIndex, endIndex);
}
} else {
for (int i = 0; i < groups; i++) {
int beginIndex = subLen * i;
int endIndex = beginIndex + subLen;
if (endIndex > s.length())
endIndex = s.length();
strs[i] = s.substring(beginIndex, endIndex);
}
}
return strs;
}
मैं निम्नलिखित जावा 8 समाधान का उपयोग करता हूं:
public static List<String> splitString(final String string, final int chunkSize) {
final int numberOfChunks = (string.length() + chunkSize - 1) / chunkSize;
return IntStream.range(0, numberOfChunks)
.mapToObj(index -> string.substring(index * chunkSize, Math.min((index + 1) * chunkSize, string.length())))
.collect(toList());
}
जावा 8 समाधान ( इस तरह लेकिन थोड़ा सरल):
public static List<String> partition(String string, int partSize) {
List<String> parts = IntStream.range(0, string.length() / partSize)
.mapToObj(i -> string.substring(i * partSize, (i + 1) * partSize))
.collect(toList());
if ((string.length() % partSize) != 0)
parts.add(string.substring(string.length() / partSize * partSize));
return parts;
}
मैंने @Alan मूर से एक टिप्पणी में स्वीकार किए गए समाधान के बारे में पूछा कि कैसे नई कहानियों के साथ तार को संभाला जा सकता है। उन्होंने DOTALL का उपयोग करने का सुझाव दिया।
उनके सुझाव का उपयोग करते हुए मैंने एक छोटा सा नमूना बनाया कि यह कैसे काम करता है:
public void regexDotAllExample() throws UnsupportedEncodingException {
final String input = "The\nquick\nbrown\r\nfox\rjumps";
final String regex = "(?<=\\G.{4})";
Pattern splitByLengthPattern;
String[] split;
splitByLengthPattern = Pattern.compile(regex);
split = splitByLengthPattern.split(input);
System.out.println("---- Without DOTALL ----");
for (int i = 0; i < split.length; i++) {
byte[] s = split[i].getBytes("utf-8");
System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
}
/* Output is a single entry longer than the desired split size:
---- Without DOTALL ----
[Idx: 0, length: 26] - [B@17cdc4a5
*/
//DOTALL suggested in Alan Moores comment on SO: https://stackoverflow.com/a/3761521/1237974
splitByLengthPattern = Pattern.compile(regex, Pattern.DOTALL);
split = splitByLengthPattern.split(input);
System.out.println("---- With DOTALL ----");
for (int i = 0; i < split.length; i++) {
byte[] s = split[i].getBytes("utf-8");
System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s);
}
/* Output is as desired 7 entries with each entry having a max length of 4:
---- With DOTALL ----
[Idx: 0, length: 4] - [B@77b22abc
[Idx: 1, length: 4] - [B@5213da08
[Idx: 2, length: 4] - [B@154f6d51
[Idx: 3, length: 4] - [B@1191ebc5
[Idx: 4, length: 4] - [B@30ddb86
[Idx: 5, length: 4] - [B@2c73bfb
[Idx: 6, length: 2] - [B@6632dd29
*/
}
लेकिन मुझे https://stackoverflow.com/a/3760193/1237974 पर @Jon Skeets solution भी पसंद है। बड़ी परियोजनाओं में स्थिरता के लिए जहां हर कोई नियमित रूप से समान रूप से अनुभवी नहीं होता है, मैं शायद जोंस समाधान का उपयोग करूंगा।
एक और जानवर बल समाधान हो सकता है,
String input = "thequickbrownfoxjumps";
int n = input.length()/4;
String[] num = new String[n];
for(int i = 0, x=0, y=4; i<n; i++){
num[i] = input.substring(x,y);
x += 4;
y += 4;
System.out.println(num[i]);
}
जहां कोड सबस्ट्रिंग के साथ स्ट्रिंग के माध्यम से कदम रखता है
import static java.lang.System.exit;
import java.util.Scanner;
import Java.util.Arrays.*;
public class string123 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("Enter String");
String r=sc.nextLine();
String[] s=new String[10];
int len=r.length();
System.out.println("Enter length Of Sub-string");
int l=sc.nextInt();
int last;
int f=0;
for(int i=0;;i++){
last=(f+l);
if((last)>=len) last=len;
s[i]=r.substring(f,last);
// System.out.println(s[i]);
if (last==len)break;
f=(f+l);
}
System.out.print(Arrays.tostring(s));
}}
परिणाम
Enter String
Thequickbrownfoxjumps
Enter length Of Sub-string
4
["Theq","uick","brow","nfox","jump","s"]
@Test
public void regexSplit() {
String source = "Thequickbrownfoxjumps";
// define matcher, any char, min length 1, max length 4
Matcher matcher = Pattern.compile(".{1,4}").matcher(source);
List<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(source.substring(matcher.start(), matcher.end()));
}
String[] expected = {"Theq", "uick", "brow", "nfox", "jump", "s"};
assertArrayEquals(result.toArray(), expected);
}
यहाँ मेरा संस्करण RegEx और Java 8 स्ट्रीम पर आधारित है। यह उल्लेख के लायक है कि Matcher.results()
जावा 9 के बाद से यह विधि उपलब्ध है।
टेस्ट शामिल थे।
public static List<String> splitString(String input, int splitSize) {
Matcher matcher = Pattern.compile("(?:(.{" + splitSize + "}))+?").matcher(input);
return matcher.results().map(MatchResult::group).collect(Collectors.toList());
}
@Test
public void shouldSplitStringToEqualLengthParts() {
String anyValidString = "Split me equally!";
String[] expectedTokens2 = {"Sp", "li", "t ", "me", " e", "qu", "al", "ly"};
String[] expectedTokens3 = {"Spl", "it ", "me ", "equ", "all"};
Assert.assertArrayEquals(expectedTokens2, splitString(anyValidString, 2).toArray());
Assert.assertArrayEquals(expectedTokens3, splitString(anyValidString, 3).toArray());
}
public static String[] split(String input, int length) throws IllegalArgumentException {
if(length == 0 || input == null)
return new String[0];
int lengthD = length * 2;
int size = input.length();
if(size == 0)
return new String[0];
int rep = (int) Math.ceil(size * 1d / length);
ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_16LE));
String[] out = new String[rep];
byte[] buf = new byte[lengthD];
int d = 0;
for (int i = 0; i < rep; i++) {
try {
d = stream.read(buf);
} catch (IOException e) {
e.printStackTrace();
}
if(d != lengthD)
{
out[i] = new String(buf,0,d, StandardCharsets.UTF_16LE);
continue;
}
out[i] = new String(buf, StandardCharsets.UTF_16LE);
}
return out;
}
public static List<String> getSplittedString(String stringtoSplit,
int length) {
List<String> returnStringList = new ArrayList<String>(
(stringtoSplit.length() + length - 1) / length);
for (int start = 0; start < stringtoSplit.length(); start += length) {
returnStringList.add(stringtoSplit.substring(start,
Math.min(stringtoSplit.length(), start + length)));
}
return returnStringList;
}