使用分隔值对数组进行排序

时间:2013-09-18 11:58:48

标签: java arrays sorting groovy

我有一个数组值为'int.int.int'

的数组

String[] tab = [ '100.2.0' , '5.7.4' , '7.6.1' , '5.6.4' ]

我想用第一个数字对这个数组进行排序,然后按第二个数字排序第一个排序的结果仍然保持数组按第一个值排序,而第三个数字排序相同。预期结果:

['5.6.4','5.7.4','7.6.1','100.2.0']

最简单的解决方案是创建辅助数组并使用for循环,但我想知道是否可以更简单地做到这一点。我也尝试过使用groovy排序

tab.sort { it -~ /\./ }

我已经删除了分隔符和已排序的元素,就像它们是整数一样,但它不适用于例如这样的值

[ '2.12.1' , '10.5.2' , '5.2.3' ]

输出

[ '5.2.3' , '10.5.2' , '2.12.1' ]

任何想法如何以简单的方式对其进行排序,而不是通过创建新数组并通过原始数组迭代3次?

5 个答案:

答案 0 :(得分:0)

撰写Comparator周围的自定义split()。这会给你一个String[]。将两个数组的第一个值转换为整数并进行比较。如果它们相等,则将后两个值转换为整数并进行比较等。如果所有三对整数相等,则值相等。

答案 1 :(得分:0)

可以这样做:

tab.sort { a, b -> [ a, b ]*.tokenize( '.' )*.
                           collect { it.toInteger() }
                           .transpose()
                           .findResult { x, y -> x <=> y ?: null } }

或(可以说是更整洁)

tab.sort { a, b ->
    [ a, b ]*.tokenize( '.' )
             .transpose()
             .findResult { x, y ->
                  x.toInteger() <=> y.toInteger() ?: null
              }
}

或者,如果版本号可以是不同数量的整数(即:1.61.7.43.3):

tab.sort { a, b ->
    [ a, b ]*.tokenize( '.' ).with { u, v ->
        [ u, v ].transpose().findResult { x, y ->
             x.toInteger() <=> y.toInteger() ?: null
        } ?: u.size() <=> v.size()
    }
}

或使用自定义比较器; - )

答案 2 :(得分:0)

使用Arrays.sort(....)方法,并为其指定Comparator,其中包含以下比较(字符串a,字符串b)方法:

public int compare (String a, String b) {
    String[] avals = a.split("\\.");
    String[] bvals = b.split("\\.");
    for (int i = 0; i < avals.length; a++) {
        int diff = Integer.parseInt(bvals[i]) - Integer.parseInt(avals[i]);
        if (diff != 0) {
            return diff;
        }
    }
    return 0;
}

答案 3 :(得分:0)

如果你想尽可能少地创建临时对象,你必须自己在比较器内部实现解析。

public static final class XComparator implements Comparator<String>
{
  public static final Comparator<String> INSTANCE = new XComparator();
  private XComparator(){}

  public int compare(String o1, String o2)
  {
    final int l1=o1.length(), l2=o2.length();
    for(int p1=0, p2=0;; p1++, p2++)
    {
      int v1=0, v2=0;
      for(;p1<l1 && o1.charAt(p1)!='.';p1++) v1=nextChar(v1, o1.charAt(p1));
      for(;p2<l2 && o2.charAt(p2)!='.';p2++) v2=nextChar(v2, o2.charAt(p2));
      if(v1<v2) return -1; else if(v1>v2) return +1;
      if(p1==l1) return p2==l2? 0: -1;
      else if(p2==l2) return +1;
    }
  }
  private int nextChar(int v, char ch)
  {
    if(ch<'0'||ch>'9') throw new IllegalArgumentException();
    return v*10+ch-'0';
  }
}

然后你可以说,例如:

String[] tab = { "100.2.0" , "5.7.4" , "7.6.1" , "5.6.4", "5", "3.4", "7.6" };
System.out.println(Arrays.toString(tab));
Arrays.sort(tab, XComparator.INSTANCE);
System.out.println(Arrays.toString(tab));

然而,对于大型数据集,仍然可以在排序之前转换为预先解析的表示(并在之后转换回来)比在比较器内进行实时解析更快。

答案 4 :(得分:0)

我们的想法是将每个字符串转换为整数元组(例如,将它命名为NumberInfo),即“100.2.0”=&gt; {100,2,0},因为整数表示对于执行比较很有用(比较用于对项目进行排序)。

因此,在将List<String>转换为List<NumberInfo>后,可以对List<NumberInfo>进行排序。

“元组”:

class NumberInfo {
    private int a;
    private int b;
    private int c;

    private NumberInfo(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    int getA() {
        return a;
    }

    int getB() {
        return b;
    }

    int getC() {
        return c;
    }

    public static NumberInfo fromString(String s) {
        String[] itemComponents = s.split("[.]");
        if (itemComponents.length != 3) {
            throw new IllegalArgumentException("Three comma delimited components expected");
        }

        int a = Integer.parseInt(itemComponents[0]);
        int b = Integer.parseInt(itemComponents[1]);
        int c = Integer.parseInt(itemComponents[2]);

        NumberInfo numberInfo = new NumberInfo(a, b, c);
        return numberInfo;
    }

    @Override
    public String toString() {
        return a + "." + b + "." + c;
    }
}

元组比较器:

class NumberInfoComparator implements Comparator<NumberInfo> {
    @Override
    public int compare(NumberInfo o1, NumberInfo o2) {
        int result = Integer.compare(o1.getA(), o2.getA());
        if (result != 0)
            return result;

        result = Integer.compare(o1.getB(), o2.getB());
        if (result != 0) {
            return result;
        }

        result = Integer.compare(o1.getC(), o2.getC());
        return result;
    }
}

主要方法:

public static void main(String[] args) {
    String[] tab = { "100.2.0" , "5.7.4" , "7.6.1" , "5.6.4" };

    ArrayList<NumberInfo> numberInfoList = new ArrayList<NumberInfo>();
    for (String item : tab) {
        NumberInfo numberInfo = NumberInfo.fromString(item);
        numberInfoList.add(numberInfo);
    }

    NumberInfoComparator numberInfoComparator = new NumberInfoComparator();
    Collections.sort(numberInfoList, numberInfoComparator);

    for (NumberInfo numberInfo : numberInfoList) {
        System.out.println(numberInfo);
    }
}