n 번째 문자마다 문자열 분할


78

JavaScript에서 이것은 3 번째 문자마다 문자열을 분할하는 방법입니다.

"foobarspam".match(/.{1,3}/g)

Java에서 이것을 수행하는 방법을 알아 내려고 노력하고 있습니다. 포인터가 있습니까?


이 작업에는 Regex를 사용하지 않습니다.
kennytm

3
확인. 그렇다면 무엇을 제안 하시겠습니까?
Vijay Dev

1
Simon의 대답과 같습니다.
kennytm

나는 당신의 추천을 두 번째입니다. 설치할 추가 라이브러리가없는 Simon의 솔루션은 훌륭하게 작동했습니다.
harperville

답변:


134

다음과 같이 할 수 있습니다.

String s = "1234567890";
System.out.println(java.util.Arrays.toString(s.split("(?<=\\G...)")));

다음을 생성합니다.

[123, 456, 789, 0]

정규식은 (?<=\G...)이 빈 문자열과 일치하는 마지막 경기 ( \G다음) 세 개의 문자 ( ...) 전에 (그것을 (?<= ))


16
나는 누군가가 정규 표현식을 좋아하지 않기 때문에이 답변에 투표했다고 생각하고 싶지 않습니다.
William Brendel

55
최고 정규식 모조에 대한 미친 소품이지만,이 코드의 독자로서 나는 당신을 사냥하고 당신의 집에 달걀을 넣을 것입니다. :)
Kevin Bourrillion

4
올바르게 명명 된 함수 (예 : splitIntoParts)를 통해이를 호출하고 해당 줄을 코드에 직접 포함하지 않는 한 모든 것이 좋습니다. 그렇지 않으면 사냥을 시작하십시오 :)
GreenieMeanie

3
이 트릭을 무섭게 만드는 이유 중 하나는 모든 언어에서 작동하지 않는다는 것입니다. 예를 들어 자바 스크립트는을 지원하지 않으며 \GPython은 0 개의 문자와 일치하는 정규식에서 분할되지 않습니다. 하지만 자바가 다른 모든 언어와 마찬가지로 "모든 일치 항목 가져 오기"메소드를 가지고 있다면 처음에 @Bart라는 트릭을 발명 할 필요가 없었을 것입니다. ;)
Alan Moore

7
나는 이것을 내 안드로이드 스튜디오 프로젝트에 복사 / 붙여 넣기를 [123, 4567890]했고 그 결과는 다음과 같다. :(
Evren Yurtesen

83

Java는 완전한 기능을 갖춘 분할 유틸리티를 제공하지 않으므로 Guava 라이브러리 는 다음을 수행합니다.

Iterable<String> pieces = Splitter.fixedLength(3).split(string);

Splitter 용 Javadoc을 확인하십시오 . 매우 강력합니다.


7
+1 이것은 정답입니다 (또는 라이브러리를 알고 사용하십시오 )
Jonik

4
나는 정규식에 대해이 대답을 받아 들일 것입니다 ... 더 유지하기 쉽기 때문입니다 (예 : ppl이 "읽을 수있는"코드를 읽을 수있는 것보다 RegEx에 대해 아는 사람이 적다는 사실).
sivabudh

4
이미 구아바 의존성이있는 경우에만 좋습니다. 그렇지 않으면 다른 종속성을 추가해야합니다. 먼저 동료 / 시스템 설계자에게 확인하지 않고 수행해서는 안되는 작업입니다.
foo

1
하나의 방법 만 사용할 수 있도록 전체 라이브러리를 추가하는 것은 대부분의 경우 모범 사례가 아니며, 라이브러리를 추가하는 것은 엔터프라이즈 환경에서 항상 중요한 결정입니다.
GaboSampaio

50
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;
    }
}

전체 원래 문자열을 포함하는 하위 문자열 모음을 유지하는 경우 새 String 메서드는 실제로 (n-1) * sizeof (int)를 낭비합니다. 새로운 Strings의 char 배열은 동일한 메모리를 사용하지만 각 배열에는 별도의 길이 필드가 있습니다. 즉, 나중에 하위 문자열이 삭제되면 새 문자열이 메모리를 줄일 수 있습니다. 원래 문자열이 너무 크지 않으면 어느 쪽이든 걱정하지 않을 것입니다.
ILMTitan

@DenisTulskiy 자세히 설명해 주시겠습니까? 이 substring메서드는 실제로 char[]데이터에 대해 부모 문자열을 사용할만큼 똑똑 합니다. 자세한 내용 은 이 답변 을 참조하십시오.
wchargin

1
@WChargin : 흠, 당신 말이 맞아요, 제가 왜 그 댓글을 썼는지 모르겠어요. 삭제하겠습니다. 감사.
Denis Tulskiy 2013-06-05

7

Bart Kiers 답변 외에도 동일한 의미를 가진 ...세 문자를 나타내는 정규식 표현식에서 세 개의 점을 사용하는 대신 가능하다는 것을 추가하고 싶습니다 .{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


3

늦은 입장.

다음은 하나의 라이너 인 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]

5
"a one liner";)
Chris

1

이것은 늦은 대답이지만 어쨌든 새로운 프로그래머가 볼 수 있도록 그것을 공개하고 있습니다.

정규 표현식을 사용하려면 원하지 않는 경우 타사 라이브러리에 의존하지 않으려면, 당신은 사이 걸리는 대신이 방법을 사용할 수 있습니다 89,920100,113 A의 나노초 2.80 GHz의 CPU (밀리 초 미만). Simon Nickerson의 예만큼 예쁘지는 않지만 작동합니다.

   /**
     * 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()]);
    }

1

일반 자바 사용 :

    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).


0

n 번째 문자마다 문자열을 분할하여 List의 각 인덱스에 넣을 수도 있습니다.

여기에 Sequence라는 문자열 목록을 만들었습니다.

목록 <문자열> 시퀀스

그런 다음 기본적으로 문자열 "KILOSO"를 2 단어마다 분할합니다. 따라서 'KI' 'LO' 'SO'는 Sequence라는 목록의 별도 색인에 통합됩니다.

문자열 S = KILOSO

Sequence = Arrays.asList (S.split ( "(? <= \ G ..)"));

그래서 내가 할 때 :

System.out.print (시퀀스)

다음과 같이 인쇄되어야합니다.

[KI, LO, SO]

내가 쓸 수 있는지 확인하려면 :

System.out.print (Sequence.get (1))

다음과 같이 인쇄됩니다.

봐라


0

최근에이 문제가 발생했으며 여기에 제가 생각 해낸 해결책이 있습니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.