A'nın a'dan önce gelmesi ve B'nin b'den önce gelmesi için Özel Sıralama


11

Bunun gibi renklerin bir listesi var:

Pembe, mavi, kırmızı, mavi, gri, yeşil, mor, siyah ... vb

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

Bazı meyve renklerini filtrelemek gibi bazı ara işlemler var, şimdi sıralı olarak sıralanmasını istediğim filtreli sonuçlarla kaldım:

Mavi, siyah, mavi, gri, yeşil, pembe, mor, kırmızı

Denedim :

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

Beklendiği gibi çalışmıyor.

Çıktı aşağıdaki gibidir:

siyah, mavi, mavi, yeşil, gri, pembe, mor, kırmızı

Aşağıdakileri istiyorum:

Mavi, siyah, mavi, gri, yeşil, pembe, mor, kırmızı


2
Siyah, Gri'den önce mavi ve yeşilden önce gelmemeli mi?
Ravindra Ranwala

3
aönce usonuç doğrudur
Jens

2
@RavindraRanwala, Mavi 'nin B sermaye ama geri s' b değildir.
Vishwa Ratna

2
Denedim, ama bu özel emri vermiyor. [black, Blue, blue, green, Grey, Pink, purple, Red]@ Chrylis-onstrike- verir
Ravindra Ranwala

2
Sermaye muhafazasının alt kasadan önce gelmesini istiyorsanız, o zaman kasa göz ardı etmek istediğiniz son şeydir.
Teepeemm

Yanıtlar:


8

Benim çözüm Comparator.thenComparing()yöntem kullanarak iki adımda sıralama kullanmaktır .

İlk olarak, Dizeleri yalnızca ilk karakter yoksayma durumu ile karşılaştırın. Dolayısıyla, aynı ilk karaktere sahip gruplar (hangi durumda olursa olsun) şimdiye kadar ayrılmadan kalır. Sonra ikinci adımda sıralanmamış alt grupları sıralamak için normal alfabetik sıralamayı uygulayın.

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

Belki hala optimize edilebilir, ancak istenen sonucu verir:

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


Öğesinin okunabilirliği için bir düzenleme yapıldı Comparator. Ama evet, bu sadece OP'nin çok fazla vurgulamadığı String'in ilk karakterini karşılaştırdığını varsayar .
Naman

8

Kendi Kurallarınızı tanımlamak için RuleBasedCollator'ı kullanabilirsiniz .

Özel kural örneği :

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

Yukarıdaki kural, dize karşılaştırılırken Chem büyük hem de küçük harflerin hem büyük hem de küçük harflerden önce görüneceği için kodu çözülür 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);

Çıktı:

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

Düzenleme:customRules El ile yazmak yerine, kodu oluşturmak için aşağıdakileri kullanabilirsiniz.

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

2
oluşturma String customRulesile otomatizm olabilir IntStream:IntStream.range('a', 'z' + 1) .mapToObj(Character::toString) .flatMap(ch -> Stream.of("<", ch.toUpperCase(), "<", ch)) .collect(Collectors.joining(""))
lczapski

@lczapski, bir şekilde .mapToObj(Character::toString)çözülmeyecek, sanırım kullanmanız gerekiyor.mapToObj(c -> Character.toString((char) c))
Vishwa Ratna

mapToObj(Character::toString)yalnızca Java 11 veya daha yenisinde çalışır.
Holger

@Holger Tamam, Sistem (JDK-8) ve benim üzerinde çalıştığımız mapToObj(Character::toString)çözülmüş elde değildi, ama böyle casting yapıyor sonunda yüzden fikri sevdim.mapToObj(c -> Character.toString((char) c))
Vishwa Ratna

3
Ben tercih ederimIntStream.rangeClosed('a', 'z').flatMap(c -> IntStream.of(c,Character.toUpperCase(c))) .mapToObj(c -> Character.toString((char)c)) .collect(Collectors.joining("<", "<", ""));
Holger

0

Her harf için önce büyük / küçük harfe duyarlı olmayan bir karşılaştırma yapan bir yönteme ihtiyacınız vardır, ardından bir eşleşme varsa her harf için büyük / küçük harfe duyarlı bir karşılaştırma gerçekleştirin:

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

Daha sonra bu yöntemi 'e aktarabilirsiniz Stream.sorted.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.