Dize "Thequickbrownfoxjumps"
Java'da eşit büyüklükteki alt dizelere nasıl bölünür ? Örneğin. "Thequickbrownfoxjumps"
4 eşit büyüklükte çıktı vermelidir.
["Theq","uick","brow","nfox","jump","s"]
Benzer Soru:
Dize "Thequickbrownfoxjumps"
Java'da eşit büyüklükteki alt dizelere nasıl bölünür ? Örneğin. "Thequickbrownfoxjumps"
4 eşit büyüklükte çıktı vermelidir.
["Theq","uick","brow","nfox","jump","s"]
Benzer Soru:
Yanıtlar:
Tek satırlık normal ifade sürümü:
System.out.println(Arrays.toString(
"Thequickbrownfoxjumps".split("(?<=\\G.{4})")
));
\G
önceki maçın bittiği konumla eşleşen sıfır genişlikli bir iddiadır. Önceki eşleşme yoksa , girişin başlangıcıyla aynı şekilde eşleşir \A
. Çevreleyen bakış, son maçın sonundan itibaren dört karakter olan konumla eşleşir.
Her ikisi de geriye doğru bakma ve \G
gelişmiş normal ifade özellikleridir ve tüm tatlar tarafından desteklenmez. Ayrıca, \G
onu destekleyen tatlarda tutarlı bir şekilde uygulanmamaktadır. Bu numara (örneğin) Java , Perl, .NET ve JGSoft'ta çalışacak, ancak PHP (PCRE), Ruby 1.9+ veya TextMate'de (her ikisi de Oniguruma) çalışmayacaktır. JavaScript'ler /y
(yapışkan bayrak) kadar esnek \G
değildir ve JS geriye bakmayı desteklese bile bu şekilde kullanılamaz.
Ben ille olmadığını belirtmeliyim tavsiye diğer seçenekleri varsa bu çözümü. Diğer yanıtlardaki normal ifade olmayan çözümler daha uzun olabilir, ancak aynı zamanda kendi kendini belgeliyorlar; bu hemen hemen bunun tam tersi . ;)
Ayrıca, bu, \G
arkaya bakma kullanımını desteklemeyen Android'de çalışmaz .
String.substring()
bir normal ifade yerine kullanmak , birkaç ekstra kod satırı gerektirirken, 5 kat daha hızlı bir yerde çalışacaktır ...
(?s)
regex: (?s)(?<=\\G.{4})
.
java.util.regex.PatternSyntaxException: Look-behind pattern matches must have a bounded maximum length
Bunu basit aritmetik ve dizgi işlemleriyle yapmak oldukça kolaydır:
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;
}
Bunun için bir normal ifade kullanmaya gerçekten değeceğini sanmıyorum.
DÜZENLEME: Normal ifade kullanmama nedenim:
Splitter.fixedLength(4)
seanizer'ın önerdiği gibi Guava's'ı öneririm.
Google Guava ile bu çok kolaydır :
for(final String token :
Splitter
.fixedLength(4)
.split("Thequickbrownfoxjumps")){
System.out.println(token);
}
Çıktı:
Theq
uick
brow
nfox
jump
s
Ya da sonuca bir dizi olarak ihtiyacınız varsa, bu kodu kullanabilirsiniz:
String[] tokens =
Iterables.toArray(
Splitter
.fixedLength(4)
.split("Thequickbrownfoxjumps"),
String.class
);
Referans:
Not: Ayırıcı yapısı yukarıda satır içi olarak gösterilmiştir, ancak Ayırıcılar değişmez ve yeniden kullanılabilir olduğundan, bunları sabitlerde saklamak iyi bir uygulamadır:
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'ın guava genel amaçlı kitaplıklarını kullanıyorsanız (ve oldukça dürüst olmak gerekirse, herhangi bir yeni Java projesi muhtemelen olmalıdır ), bu Splitter sınıfı için delice önemsizdir :
for (String substring : Splitter.fixedLength(4).split(inputString)) {
doSomethingWith(substring);
}
ve işte bu . Kadar kolay!
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()
ve len
her ikisi de int
ler, çağrı ceiling
(src.length () + len - 1) / len: diğer bazı cevapların nasıl yapıyorlar kontrol - Ne istediğini gerçekleştirerek değil
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
döngülere karşı bir şeyiniz var mı?
for
döngü aslında bunun için daha 'doğal' bir seçimdir :-) Bunu işaret ettiğiniz için teşekkürler.
Sen kullanabilirsiniz substring
dan String.class
(durumları işleme) ya da gelen Apache lang commons (sizin için istisnalar kolları)
static String substring(String str, int start, int end)
Bir döngü içine koyun ve gitmeniz iyi olur.
substring
Standart String
sınıftaki yöntemin nesi yanlış ?
Bu basit çözümü tercih ederim:
String content = "Thequickbrownfoxjumps";
while(content.length() > 4) {
System.out.println(content.substring(0, 4));
content = content.substring(4);
}
System.out.println(content);
substring
uygulaması, 2012 ortasında offset
ve count
alanları String
sınıftan kaldırıldığında Java 7, güncelleme 6 ile değişti . Yani substring
bu cevap verilmeden çok önce karmaşıklığı lineer hale geldi. Ancak örnek gibi küçük bir dizi için, hala yeterince hızlı ve daha uzun dizeler için çalışıyor… bu görev pratikte nadiren gerçekleşir.
İşte Java8 akışlarını kullanan tek satırlık bir uygulama:
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();
Aşağıdaki çıktıyı verir:
[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);
İşte Java 8 kullanan tek satırlık bir sürüm IntStream dilim başlangıçların endeksleri belirlemek için:
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);
Eğer bölmek, örneğin, eşit geriye dize bölmek, yani sağdan sola istediğiniz 1010001111
için [10, 1000, 1111]
, burada kod:
/**
* @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;
}
aşağıdaki java 8 çözümünü kullanıyorum:
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());
}
(Gibi Java 8 çözüm bu ama biraz daha basit):
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 Moore'a kabul edilen çözüme bir yorumda satırsonu içeren dizelerin nasıl işlenebileceğini sordum . DOTALL kullanmayı önerdi.
Önerisini kullanarak bunun nasıl çalıştığına dair küçük bir örnek oluşturdum:
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
*/
}
Ama @Jon Skeets çözümünü https://stackoverflow.com/a/3760193/1237974'te de seviyorum . Düzenli ifadelerde herkesin eşit derecede deneyimli olmadığı daha büyük projelerde sürdürülebilirlik için muhtemelen Jons çözümünü kullanırdım.
Başka bir kaba kuvvet çözümü şunlar olabilir:
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]);
}
Kodun sadece alt dizelerle dizede geçtiği yer
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));
}}
Sonuç
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 ve Java 8 akışlarına dayalı sürümüm. Bu Matcher.results()
yöntemin Java 9'dan beri mevcut olduğunu belirtmekte fayda var .
Test dahildir.
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;
}