3

特定の並べ替えをしたい。私はJavaの同等のインターフェースを使用しています。つまり、比較メソッドの戻り値は、比較された2つの同等性に応じて-1 +1または0を返す必要があり、コレクションを使用してソートしています。私の悩みは、私がどのように比較したいかから来ます。

次のいずれかで構成されるキーを持っています

[keyName]  
[siteName].[keyName]  
[siteName].[pageName].[keyName]  

例として「mysite.alampshade.color」

トリッキーな部分は、サイトを最初に並べ替え、次にキー名、次に pageName を並べ替える必要があることです。ただし、最初にキー名、次にサイト名、プロパティへのセクション数の順に並べます。ごめん。少し複雑です。例が役立つ場合があります。順序は次のとおりです。

alpha  
beta  
charlie  
sitea.alpha  
sitea.charlie  
sitea.pagea.beta  
sitea.pageb.beta  
sitea.pagea.charlie  
siteb.alpha  
siteb.delta  
siteb.pagef.alpha  
siteb.pageb.echo  
siteb.pageb.golf  
siteb.pagea.hotel  
siteb.pageb.hotel  
siteb.pagec.hotel  

私はさまざまな方法を試し、コードを数回捨てましたが、それでも完璧にはなりません。一部のJavaではないにしても、いくつかの疑似コードが非常に役立ちます。

EDIT:別の例を理解するためにおそらく簡単に追加するには、次の例を必要に応じてソートします

a  
b  
c  
z  
a.b  
a.c  
a.d  
a.z  
a.b.a  
a.c.a  
a.b.b  
a.b.c  
a.c.c  
a.a.d  
b.a  
b.b  
b.z  
b.a.a  
b.b.a  
b.a.b  
c.c.f  
4

4 に答える 4

2

今はいいはずです。

public int compare(String a, String b) {
String[] partsA = a.split("\\.");
String[] partsB = b.split("\\.");

// If first term is different, we exit.
if (partsA[0].compareTo(partsB[0]) != 0) return partsA[0].compareTo(partsB[0]);

// Else, first term is identical.
else {
    // Same number of parts
    if (partsA.length == partsB.length) {
        // 2 parts, we compare the 2nd part.
        if (partsA.length == 2) {
            return partsA[1].compareTo(partsB[1]);
        // 3 parts, we compare the 3rd part first, then the 2nd part        
        } else {
            if (partsA[2].compareTo(partsB[2]) != 0) return partsA[2].compareTo(partsB[2]);
            return partsA[1].compareTo(partsB[1]);
        }

    // Different number of parts
    } else {
        // If A has only 1 part, it's first
        if (partsA.length == 1) return -1;
        // If B has only 1 part, it's first
        if (partsB.length == 1) return 1;

        // Case 2 vs 3 parts, we compare the 3rd part with the 2nd part of the other. If it's equal, the shorter is first.
        if (partsA.length == 3) {
            if (partsA[2].compareTo(partsB[1]) != 0) return partsA[2].compareTo(partsB[1]);
            else return 1;
        } else {
            if (partsA[1].compareTo(partsB[2]) != 0) return partsA[1].compareTo(partsB[2]);
            else return -1;
        }           
    }
}
}
于 2013-03-21T14:15:34.077 に答える
2

別のオプションとして、再帰的にすることで、エントリがさらに増えた場合に問題を回避できます。

import java.util.ArrayList; java.util.Arrays をインポートします。java.util.Comparator をインポートします。java.util.List をインポートします。

public class SortTest {
    public static void main(String[] args) {
        String[] test = new String[]{
            "a",
            "b",
            "b.a",
            "b.a.a",
            "a.a.a",
            "a.b.a",
            "a.a",
            "a.b",
            "b.a.b",
            "b.b.a"
        };

        Arrays.sort(test, new Comparator<String>() {

        int compareComplexList(List<String> a, List<String> b, List<int[]> positions, int order ) {

          int minimum = a.size() < b.size() ? a.size() - 1 : b.size() - 1;   

          if (a.get(positions.get(minimum)[order]).compareTo(b.get(positions.get(minimum)[order])) != 0)
                return a.get(positions.get(minimum)[order]).compareTo(b.get(positions.get(minimum)[order]));
          else if (order < minimum - 1) return compareComplexList(a,b, positions, ++order);
          else return Double.compare(a.size(),b.size());
        }

        public int compare(String a, String b) {
          List<String> partsA = Arrays.asList(a.split("\\."));
          List<String> partsB = Arrays.asList(b.split("\\."));
          List<int[]>  orders = new ArrayList<int[]>();

          orders.add(new int[] {0});
          orders.add(new int[] {0,1});
          orders.add(new int[] {0,2,1});

          return compareComplexList(partsA, partsB, orders,0);
        }
        });
        System.out.println("Sorted: "+Arrays.toString(test));
    }

}
于 2013-03-21T16:44:50.197 に答える
1

私の他の答えはあまりにもぎこちなくなり始めました。より良い、より自然な解決策は次のとおりです。

public class StrangeComparator {
  private static class Entry implements Comparable<Entry> {
    // What to split with.
    static final String dot = Pattern.quote(".");
    // The parts.
    final String key;
    final String page;
    final String site;

    public Entry(String s) {
      String [] parts = s.split(dot);
      switch (parts.length) {
        case 1:
          key = parts[0];
          page = "";
          site = "";
          break;

        case 2:
          key = parts[1];
          page = "";
          site = parts[0];
          break;

        case 3:
          key = parts[2];
          page = parts[1];
          site = parts[0];
          break;

        default:
          throw new IllegalArgumentException("There must be at least one part to an entry.");
      }
    }

    @Override
    public int compareTo(Entry t) {
      int diff = site.compareTo(t.site);
      if ( diff == 0 ) {
        diff = page.compareTo(t.page);
      }
      if ( diff == 0 ) {
        diff = key.compareTo(t.key);
      }
      return diff;
    }

    @Override
    public String toString () {
      return (site.length() > 0 ? site + "." : "")
              + (page.length() > 0 ? page + "." : "")
              + key;
    }
  }

  public void test() {
    String[] test = new String[]{
      "alpha",
      "beta",
      "charlie",
      "zeta", // Added to demonstrate correctness.
      "sitea.alpha",
      "sitea.charlie",
      "sitea.pagea.beta",
      "sitea.pageb.beta",
      "sitea.pagea.charlie",
      "siteb.alpha",
      "siteb.delta",
      "siteb.pagef.alpha",
      "siteb.pageb.echo",
      "siteb.pageb.golf",
      "siteb.pagea.hotel",
      "siteb.pageb.hotel",
      "siteb.pagec.hotel"
    };
    Arrays.sort(test);
    System.out.println("Normal sort: " + Separator.separate("\n", "\n", test));
    Entry[] entries = new Entry[test.length];
    for ( int i = 0; i < test.length; i++ ) {
      entries[i] = new Entry(test[i]);
    }
    Arrays.sort(entries);
    System.out.println("Special sort: " + Separator.separate("\n", "\n", entries));
  }

  public static void main(String args[]) {
    new StrangeComparator().test();
  }
}

出力順序は次のとおりです。

alpha
beta
charlie
zeta
sitea.alpha
sitea.charlie
sitea.pagea.beta
sitea.pagea.charlie
sitea.pageb.beta
siteb.alpha
siteb.delta
siteb.pagea.hotel
siteb.pageb.echo
siteb.pageb.golf
siteb.pageb.hotel
siteb.pagec.hotel
siteb.pagef.alpha

どちらがあなたの言うことをしますが、あなたの例とは一致しません。

于 2013-03-21T17:07:47.177 に答える
0

別の方法があります。コンポーネントに含まれるパーツが3つ未満の場合は、最初にパーツを追加してたるみを取ります。次に、並べ替え順序配列を使用して、次に比較する列を定義します。

  public void test() {
    String[] test = new String[]{
      "alpha",
      "beta",
      "charlie",
      "zeta", // Added to demonstrate correctness.
      "sitea.alpha",
      "sitea.charlie",
      "sitea.pagea.beta",
      "sitea.pageb.beta",
      "sitea.pagea.charlie",
      "siteb.alpha",
      "siteb.delta",
      "siteb.pagef.alpha",
      "siteb.pageb.echo",
      "siteb.pageb.golf",
      "siteb.pagea.hotel",
      "siteb.pageb.hotel",
      "siteb.pagec.hotel"
    };
    Arrays.sort(test);
    System.out.println("Normal sort: "+Arrays.toString(test));
    Arrays.sort(test, new Comparator<String>() {
      // How many columns to pad to.
      final int padTo = 3;
      // What to pad with.
      final String padWith = "";
      // What order to compare the resultant columns in.
      final int[] order = {0, 2, 1};

      @Override
      public int compare(String s1, String s2) {
        String[] s1parts = padArray(s1.split(Pattern.quote(".")), padTo, padWith);
        String[] s2parts = padArray(s2.split(Pattern.quote(".")), padTo, padWith);
        int diff = 0;
        for ( int i = 0; diff == 0 && i < order.length; i++ ) {
          diff = s1parts[order[i]].compareTo(s2parts[order[i]]);
        }
        return diff;
      }

      String [] padArray(String[] array, int padTo, String padWith) {
        String [] padded = new String[padTo];
        for ( int i = 0; i < padded.length; i++ ) {
          padded[padded.length - i - 1] = i < array.length ? array[i]: padWith;
        }
        return padded;
      }
    });
    System.out.println("Special sort: "+Arrays.toString(test));
  }

プリント(多かれ少なかれ):

Normal sort: [alpha,
 beta,
 charlie,
 sitea.alpha,
 sitea.charlie,
 sitea.pagea.beta,
 sitea.pagea.charlie,
 sitea.pageb.beta,
 siteb.alpha,
 siteb.delta,
 siteb.pagea.hotel,
 siteb.pageb.echo,
 siteb.pageb.golf,
 siteb.pageb.hotel,
 siteb.pagec.hotel,
 siteb.pagef.alpha,
 zeta]
Special sort: [alpha,
 beta,
 charlie,
 sitea.alpha,
 sitea.charlie,
 siteb.alpha,
 siteb.delta,
 zeta,
 siteb.pagef.alpha,
 sitea.pagea.beta,
 sitea.pageb.beta,
 sitea.pagea.charlie,
 siteb.pageb.echo,
 siteb.pageb.golf,
 siteb.pagea.hotel,
 siteb.pageb.hotel,
 siteb.pagec.hotel]

要件にはあいまいさがあるように見えますが、このコードは構造化されているため、簡単な調整で、比較のほとんどの解釈を非常に簡単に実現できます。

于 2013-03-21T14:39:17.597 に答える