У JavaScript це те, як ми можемо розділити рядок на кожен 3-й символ
"foobarspam".match(/.{1,3}/g)
Я намагаюся зрозуміти, як це зробити на Java. Будь-які вказівники?
У JavaScript це те, як ми можемо розділити рядок на кожен 3-й символ
"foobarspam".match(/.{1,3}/g)
Я намагаюся зрозуміти, як це зробити на Java. Будь-які вказівники?
Відповіді:
Ви можете зробити це так:
String s = "1234567890";
System.out.println(java.util.Arrays.toString(s.split("(?<=\\G...)")));
який виробляє:
[123, 456, 789, 0]
Звичайний вираз (?<=\G...)
відповідає порожньому рядку, який має останній збіг ( \G
), за яким слідують три символи ( ...
) перед ним ( (?<= )
)
\G
, і Python не розбиватиметься на регулярний вираз, який відповідає нулю символів. Але тоді, якби Java використовувала метод "отримати всі збіги", як це робить будь-яка інша мова, вам би не довелося вигадувати цей фокус спочатку @Bart. ;)
[123, 4567890]
як результат :(
Java не пропонує дуже повнофункціональних утиліт для розділення, тому бібліотеки Guava роблять:
Iterable<String> pieces = Splitter.fixedLength(3).split(string);
Перевірте Javadoc для Splitter ; це дуже потужно.
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
for (String part : getParts("foobarspam", 3)) {
System.out.println(part);
}
}
private static List<String> getParts(String string, int partitionSize) {
List<String> parts = new ArrayList<String>();
int len = string.length();
for (int i=0; i<len; i+=partitionSize)
{
parts.add(string.substring(i, Math.min(len, i + partitionSize)));
}
return parts;
}
}
substring
Метод насправді досить розумний , щоб використовувати батьківські струни char[]
для даних; див. цю відповідь, щоб дізнатися більше.
Як доповнення до відповіді Барта Кірса я хочу додати, що можливо замість того, щоб використовувати три крапки ...
у виразі регулярного виразу, які представляють три символи, які ви можете написати, .{3}
що має однакове значення.
Тоді код буде виглядати наступним чином:
String bitstream = "00101010001001010100101010100101010101001010100001010101010010101";
System.out.println(java.util.Arrays.toString(bitstream.split("(?<=\\G.{3})")));
За допомогою цього було б простіше змінити довжину рядка, і створення функції тепер є розумним із змінною довжиною вхідного рядка. Це можна зробити приблизно так:
public static String[] splitAfterNChars(String input, int splitLen){
return input.split(String.format("(?<=\\G.{%1$d})", splitLen));
}
Приклад в IdeOne: http://ideone.com/rNlTj5
Пізній вхід.
Нижче наводиться стисла реалізація за допомогою потоків Java8, одного вкладиша:
String foobarspam = "foobarspam";
AtomicInteger splitCounter = new AtomicInteger(0);
Collection<String> splittedStrings = foobarspam
.chars()
.mapToObj(_char -> String.valueOf((char)_char))
.collect(Collectors.groupingBy(stringChar -> splitCounter.getAndIncrement() / 3
,Collectors.joining()))
.values();
Вихід:
[foo, bar, spa, m]
Це пізня відповідь, але я все одно викладаю її для всіх нових програмістів:
Якщо ви не хочете використовувати регулярні вирази і не хочете покладатися на сторонні бібліотеки, замість цього ви можете використовувати цей метод, який займає від 89920 до 100113 наносекунд у центральному процесорі 2,80 ГГц (менше мілісекунди). Це не так красиво, як приклад Саймона Нікерсона, але він працює:
/**
* Divides the given string into substrings each consisting of the provided
* length(s).
*
* @param string
* the string to split.
* @param defaultLength
* the default length used for any extra substrings. If set to
* <code>0</code>, the last substring will start at the sum of
* <code>lengths</code> and end at the end of <code>string</code>.
* @param lengths
* the lengths of each substring in order. If any substring is not
* provided a length, it will use <code>defaultLength</code>.
* @return the array of strings computed by splitting this string into the given
* substring lengths.
*/
public static String[] divideString(String string, int defaultLength, int... lengths) {
java.util.ArrayList<String> parts = new java.util.ArrayList<String>();
if (lengths.length == 0) {
parts.add(string.substring(0, defaultLength));
string = string.substring(defaultLength);
while (string.length() > 0) {
if (string.length() < defaultLength) {
parts.add(string);
break;
}
parts.add(string.substring(0, defaultLength));
string = string.substring(defaultLength);
}
} else {
for (int i = 0, temp; i < lengths.length; i++) {
temp = lengths[i];
if (string.length() < temp) {
parts.add(string);
break;
}
parts.add(string.substring(0, temp));
string = string.substring(temp);
}
while (string.length() > 0) {
if (string.length() < defaultLength || defaultLength <= 0) {
parts.add(string);
break;
}
parts.add(string.substring(0, defaultLength));
string = string.substring(defaultLength);
}
}
return parts.toArray(new String[parts.size()]);
}
Використання звичайної Java:
String s = "1234567890";
List<String> list = new Scanner(s).findAll("...").map(MatchResult::group).collect(Collectors.toList());
System.out.printf("%s%n", list);
Виводить результат:
[123, 456, 789]
Зверніть увагу, що це відкидає залишки символів (у цьому випадку - 0).
Ви також можете розділити рядок на кожен n-й символ і помістити їх кожен у кожен індекс Списку:
Тут я склав список рядків з назвою Послідовність:
Список <Рядок> Послідовність
Тоді я в основному розділяю рядок "KILOSO" на кожні 2 слова. Отже, «KI» «LO» «SO» буде включено в окремий індекс Списку під назвою «Послідовність».
Рядок S = KILOSO
Послідовність = Arrays.asList (S.split ("(? <= \ G ..)"));
Отже, коли я роблю:
System.out.print (послідовність)
На ньому слід надрукувати:
[KI, LO, SO]
для перевірки я можу написати:
System.out.print (Sequence.get (1))
він надрукує:
LO
Нещодавно я зіткнувся з цією проблемою, і ось рішення, яке я придумав
final int LENGTH = 10;
String test = "Here is a very long description, it is going to be past 10";
Map<Integer,StringBuilder> stringBuilderMap = new HashMap<>();
for ( int i = 0; i < test.length(); i++ ) {
int position = i / LENGTH; // i<10 then 0, 10<=i<19 then 1, 20<=i<30 then 2, etc.
StringBuilder currentSb = stringBuilderMap.computeIfAbsent( position, pos -> new StringBuilder() ); // find sb, or create one if not present
currentSb.append( test.charAt( i ) ); // add the current char to our sb
}
List<String> comments = stringBuilderMap.entrySet().stream()
.sorted( Comparator.comparing( Map.Entry::getKey ) )
.map( entrySet -> entrySet.getValue().toString() )
.collect( Collectors.toList() );
//done
// here you can see the data
comments.forEach( cmt -> System.out.println( String.format( "'%s' ... length= %d", cmt, cmt.length() ) ) );
// PRINTS:
// 'Here is a ' ... length= 10
// 'very long ' ... length= 10
// 'descriptio' ... length= 10
// 'n, it is g' ... length= 10
// 'oing to be' ... length= 10
// ' past 10' ... length= 8
// make sure they are equal
String joinedString = String.join( "", comments );
System.out.println( "\nOriginal strings are equal " + joinedString.equals( test ) );
// PRINTS: Original strings are equal true