Разделить строку на подстроки равной длины в Java
как разделить строку "Thequickbrownfoxjumps" к подстрокам одинакового размера в Java.
Например. "Thequickbrownfoxjumps" из 4 равных размеров должен дать выход.
["Theq","uick","brow","nfox","jump","s"]
Аналогичный Вопрос:
16 ответов:
вот регулярное выражение однострочной версии:
System.out.println(Arrays.toString( "Thequickbrownfoxjumps".split("(?<=\G.{4})") ));
\Gявляется утверждением нулевой ширины, которое соответствует позиции, где закончился предыдущий матч. Если есть был нет предыдущего совпадения, он соответствует началу ввода, так же, как\A. Заключительный lookbehind соответствует позиции, которая составляет четыре символа с конца последнего матча.оба lookbehind и
\Gрасширенные функции регулярных выражений, не поддерживаемые всеми вкусами. Кроме того,\Gне реализуется последовательно через ароматы, которые поддерживают его. Этот трюк будет работать (например) в Java, Perl, .NET и JGSoft, но не в PHP (PCRE), Ruby 1.9+ или TextMate (оба Oniguruma). В JavaScript/y(липкий флаг) не так гибко, как\G, и не может быть использован таким образом, даже если JS поддерживает lookbehind.Я должен упомянуть, что я не должен рекомендую это решение, если у вас есть другие варианты. Нерегулярные решения в других ответах могут быть длиннее, но они также самодокументированы; это просто о напротив об этом. ;)
кроме того, это не работает в Android, который не поддерживает использование
\Gв lookbehinds.
это очень легко с Google Guava:
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); }
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; }
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; }
можно использовать
substringСString.class(обработка исключений) или Apache Lang commons (он обрабатывает исключения для вас)static String substring(String str, int start, int end)положите его в петлю, и вы хорошо идти.
Я бы предпочел это простое решение:
String content = "Thequickbrownfoxjumps"; while(content.length() > 4) { System.out.println(content.substring(0, 4)); content = content.substring(4); } System.out.println(content);
в случае, если вы хотите разделить строку поровну назад, т. е. справа налево, например, разделить
1010001111to[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; }
вот реализация одного лайнера с использованием потоков 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]
Я спросил @Alan Moore в комментарии к принято решение как строки с новыми строками могут быть обработаны. Он предложил использовать 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 */ }но мне нравится решение @Jon Skeets в https://stackoverflow.com/a/3760193/1237974 тоже. Для ремонтопригодности в больших проектах, где не все одинаково опытны в регулярных выражениях, я бы, вероятно, использовал Jons решение.
другое решение грубой силы может быть,
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); }
вот моя версия, основанная на регулярных выражениях и потоках Java 8. Стоит отметить, что
Matcher.results()метод доступен с Java 9.
Я использую следующее решение java 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()); }