A가 a보다 먼저, B가 b보다 먼저 오는 방식으로 사용자 정의 정렬


11

다음과 같은 색상 목록이 있습니다.

핑크, 블루, 레드, 블루, 그레이, 그린, 퍼플, 블랙 ... 등

List<String> listOfColors =  Arrays.asList("Pink", "Blue", "Red", "blue", "Grey", "green", "purple", "black");

일부 과일 색상을 필터링하는 것과 같은 중간 작업이 있습니다. 이제 필터링 된 결과가 순서대로 정렬되도록 남겨 둡니다.

블루, 블랙, 블루, 그레이, 그린, 핑크, 퍼플, 레드

나는 시도했다 :

List<String> collect = listOfColors.stream().sorted(String::compareToIgnoreCase)
        .collect(Collectors.toList());

예상대로 작동하지 않습니다.

출력은 다음과 같습니다.

블랙, 블루, 블루, 그린, 그레이, 핑크, 퍼플, 레드

나는 다음을 원한다.

블루, 블랙, 블루, 그레이, 그린, 핑크, 퍼플, 레드


2
회색이 검은 색보다 파란색과 녹색보다 먼저 나오지 않아야합니까?
Ravindra Ranwala

3
a전에 u결과가 정확합니다
Jens

2
@RavindraRanwala, BlueB 는 자본이지만 Backb 는 그렇지 않습니다.
Vishwa Ratna

2
시도했지만이 특정 순서를 제공하지는 않습니다. 그것은 준다 [black, Blue, blue, green, Grey, Pink, purple, Red]@ chrylis이-onstrike-
라빈 드라 Ranwala

2
케이싱을 더 낮은 케이싱보다 먼저 사용하려면 케이싱을 무시하는 것이 가장 좋습니다.
Teepeemm

답변:


8

내 해결책은 방법을 사용하여 두 단계로 정렬을 사용하는 Comparator.thenComparing()것입니다.

먼저 첫 번째 문자 무시 대소 문자만으로 문자열을 비교하십시오. 따라서 첫 문자가 같은 그룹 (어떤 경우에 상관없이)은 지금까지 분류되지 않은 상태로 남아 있습니다. 그런 다음 두 번째 단계에서 일반 알파벳 정렬을 적용하여 정렬되지 않은 하위 그룹을 정렬하십시오.

List<String> listOfColors =  Arrays.asList("Pink", "Blue", "Red", "blue", "Grey", "green", "purple", "black");
Comparator<String> comparator = Comparator.comparing(s -> 
        Character.toLowerCase(s.charAt(0)));
listOfColors.sort(comparator.thenComparing(Comparator.naturalOrder()));
System.out.println(listOfColors);

어쩌면 여전히 최적화 될 수는 있지만 원하는 결과를 얻을 수 있습니다.

[Blue, black, blue, Grey, green, Pink, purple, Red]


의 가독성을 수정했습니다 Comparator. 그러나 예, 이것은 OP가별로 강조하지 않은 String 의 첫 문자 만 비교한다고 가정 합니다.
나만

8

RuleBasedCollator 를 사용하여 고유 한 규칙을 정의 할 수 있습니다 .

맞춤 규칙의 예 :

String rules = "< c,C < b,B";

위의 규칙은 문자열을 비교할 때 C대문자와 소문자가 모두 대문자와 소문자보다 먼저 나타나도록 디코딩됩니다 B.

String customRules = "<A<a<B<b<C<c<D<d<E<e<F<f<G<g<H<h<I<i<J<j<K<k<L<l<M<m<N<n<O<o<P<p<Q<q<R<r<S<s<T<t<U<u<V<v<X<x<Y<y<Z<z";
RuleBasedCollator myRuleBasedCollator = new RuleBasedCollator(customRules);
Collections.sort(listOfColors,myRuleBasedCollator);
System.out.println(listOfColors);

산출:

[Blue, black, blue, Grey, green, Pink, purple, Red]

편집 :customRules 직접 작성하는 대신 아래 코드를 사용하여 코드를 생성 할 수 있습니다.

String a = IntStream.range('a', 'z' + 1).mapToObj(c -> Character.toString((char) c))
        .flatMap(ch -> Stream
            .of("<", ch.toUpperCase(), "<", ch)).collect(Collectors.joining(""));

2
창조 String customRules는 다음과 IntStream같이 자동화 될 수있다 :IntStream.range('a', 'z' + 1) .mapToObj(Character::toString) .flatMap(ch -> Stream.of("<", ch.toUpperCase(), "<", ch)) .collect(Collectors.joining(""))
lczapski

@lczapski, 어떻게 든 .mapToObj(Character::toString)해결되지 않습니다, 당신이 사용해야 할 것 같아요.mapToObj(c -> Character.toString((char) c))
Vishwa Ratna

mapToObj(Character::toString)Java 11 이상에서만 작동합니다.
Holger

@Holger 좋아, 나는 시스템 (JDK-8) 및 내에서 시도 mapToObj(Character::toString)해결하기 아니었지만, 내가 좋아하는 캐스팅을하고 결국 그래서 아이디어를 좋아.mapToObj(c -> Character.toString((char) c))
인 Vishwa 라트

3
선호합니다IntStream.rangeClosed('a', 'z').flatMap(c -> IntStream.of(c,Character.toUpperCase(c))) .mapToObj(c -> Character.toString((char)c)) .collect(Collectors.joining("<", "<", ""));
Holger

0

먼저 각 문자에 대해 대소 문자를 구분하지 않는 비교를 수행 한 다음 일치하는 경우 각 문자에 대해 대소 문자를 구분하는 비교를 수행하는 방법이 필요합니다.

public static int compare(String s1, String s2)
{
    int len, i;
    if (s1.length()<s2.length()) {
        len = s1.length();
    } else {
        len = s2.length();
    }
    for (i=0;i<len;i++) {
        if (Character.toUpperCase(s1.charAt(i)) < Character.toUpperCase(s2.charAt(i))) {
            return -1;
        } else if (Character.toUpperCase(s1.charAt(i)) > Character.toUpperCase(s2.charAt(i))) {
            return 1;
        } else if (s1.charAt(i) < s2.charAt(i)) {
            return -1;
        } else if (s1.charAt(i) > s2.charAt(i)) {
            return 1;
        }
    }
    if (s1.length() < s2.length()) {
        return -1;
    } else if (s1.length() > s2.length()) {
        return 1;
    } else {
        return 0;
    }
}

그런 다음이 메소드를에 전달할 수 있습니다 Stream.sorted.

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