2015-02-03 1 views
1

"U39,R11,U50-U55,U99"과 같은 일부 문자열 유형의 데이터가 있습니다.범위를 확장하는 방법 012 - w d +

하이픈으로 표시된 범위를 확장하여 "U39,R11,U50,U51,U52,U53,U54,U55,U99"으로 변경하는 방법은 무엇입니까?

자바 정규 표현식을 사용하여 "-"및 "-"앞에 숫자와 문자 접두사를 파악한 다음 루프를 사용하여 처음부터 끝까지 숫자를 인쇄합니다. 더 나은 해결책이 있습니까?

+0

만약'X50-A11'이 있다면? –

+0

제목이 내가 얻지 못한 말장난인가? 미래의 사용자가 "다양한 레이블을 확장하는 방법"으로 변경하는 데 도움이 될 것이라고 생각합니다. – 5gon12eder

+0

@ 5gon12eder "pun": LOL. - 내가 제 1 언어에서 문자 그대로 번역한다면 나는 아마도 "본딩 스트로크"를 생각해 낼 것입니다. 그리고 프랑스 인은 "노동 조합"을 만들 수도 있습니다. – laune

답변

0

이 같은 목록의 항목 스트림은 (오히려 기존의 반복보다는) 자바 8 스트림 꽤 좋은 사용 사례입니다 나는 합리적인 방법으로 그렇게 할 것이라고 생각한다 :

  1. 문자열을 배열로 나눕니다.) 문자열을 String.split(",")을 사용합니다.
  2. ArrayList<String> (labelsOut) 결과를 저장하십시오.
  3. 루프 labelsIn 배열이고, 각 요소 :
    • matches the pattern[A-Z][0-9]+ 상기 labelsOut 목록에 추가 할 경우. 이 패턴 ([A-Z])([0-9]+)-\1([0-9]+) (matchMatcher 객체 호출을) 일치하는 경우 그렇지
    • ,,, highlow에서 lowhigh 모든 번호를 n (Integer.valueOf(match.group(2))Integer.valueOf(match.group(3))을 사용하여) 번호를 추출 labelsOut 목록에 String.format("%s%d", match.group(1), n)를 추가합니다.
    • 그렇지 않으면 구문 오류입니다.
  4. Concatenate the stringslabelsOut 목록에서 ",".

당신은 당신이 맞는 볼 경우 0 개 이상의 공백 "," 주변의 문자 (\s*)와 "-"를 허용함으로써 정규 표현식을 조금 일반화 할 수 있습니다.

위의 절차는 성능이 아닌 교훈적인 명확성에 맞게 최적화되어 있습니다. 원하는 경우 중간 결과 중 일부를 제거 할 수 있습니다. Java 8 streams을 사용하여 코드를 "간소화"할 수도 있습니다.

+0

고마워요! String.format ("% s % d", match.group (1), n)의 의미가 확실하지 않습니다. 결과는 무엇입니까? –

+0

'match.group (1)'은 일치하는 문자 (정규 표현식에서 처음 괄호 안에있는 것)를 반환합니다 (예 :' "U"'). 'String.format'은'% s'을 인수 # 1로 전달 된 문자열로 대체하고 '% d'는 인수 # 2로 전달 된 정수 표현으로 대체합니다. 그러므로'n = 51'이라면, 형식화 된 문자열은''U51''을 읽을 것입니다. 보고 그것을 시도하십시오. – 5gon12eder

+0

늦어서 죄송 합니다만, 말씀 드린대로 모든 숫자 n을 낮은 값에서 높은 값으로 루프해야합니까? –

0

물론 다양한 방법으로이 작업을 수행 할 수 있습니다. 나는 정규식을 사용하는 것이 꽤 직접적인 접근이라고 생각한다.

class Expander { 
    private final List<String> expandedList = new ArrayList<>(); 
    private final Pattern PATTERN = Pattern.compile("([UR])(\\d+)-[UR](\\d+)"); 

    public static String expand(String input) { 
     return Arrays.stream(input.split(",")).parallel() 
      .collect(Expander::new, Expander::accept, Expander::combine) 
      .expandedList.stream().collect(Collectors.joining(",")); 
    } 

    private void accept(String item) { 
     Matcher matcher = PATTERN.matcher(item); 
     if (matcher.matches()) { 
      int from = Integer.parseInt(matcher.group(2)); 
      int to = Integer.parseInt(matcher.group(3)); 
      IntStream.rangeClosed(from, to) 
       .mapToObj(i -> matcher.group(1) + i) 
       .forEach(expandedList::add); 
     } else { 
      expandedList.add(item); 
     } 
    } 

    private Expander combine(Expander other) { 
     expandedList.addAll(other); 
     return this; 
    } 
} 

내 테스트 코드 :

public static void main(String[] args) { 
    System.out.println(Expander.expand("U23,R45,U12-U15,R7"); 
} 

인쇄합니다 U23,R45,U12,U13,U14,U15,R7

+0

답변 해 주셔서 감사합니다. 스트림을 그렇게 사용하는 방법을 본 적이 없습니다. –

+0

실제로 훨씬 좋습니다! –

+0

@BaochengLi 대단히 기쁩니다. 유용하다고 생각합니다. 스트림은 매우 익숙해지면 매우 강력하고 직관적입니다. – sprinter

관련 문제