我有一个字符串数组,它是来自外部代码的类的实例,我宁愿不改变。
我还有一个通过调用每个对象上的函数生成的一组int。所以我有
答:[string1, string2, string3]
和
B:[40, 32, 34]
如何轻松地对A进行排序,使其按B的值排序。我有可用的提升。我想按顺序对A进行排序:
[string2, string3, string1]
在javascript中你可以这样做:
B.sort(function(a,b){return A[B.indexOf(a)] < A[B.indexOf(b)];});
答案 0 :(得分:9)
在java 8中,你可以这样做
使用lambda:
String[] strings = new String[]{"string1", "string2", "string3"};
final int[] ints = new int[]{40, 32, 34};
final List<String> stringListCopy = Arrays.asList(strings);
ArrayList<String> sortedList = new ArrayList(stringListCopy);
Collections.sort(sortedList, (left, right) -> ints[stringListCopy.indexOf(left)] - ints[stringListCopy.indexOf(right)]);
或者更好,使用 Comparator :
String[] strings = new String[]{"string1", "string2", "string3"};
final int[] ints = new int[]{40, 32, 34};
final List<String> stringListCopy = Arrays.asList(strings);
ArrayList<String> sortedList = new ArrayList(stringListCopy);
Collections.sort(sortedList, Comparator.comparing(s -> ints[stringListCopy.indexOf(s)]));
答案 1 :(得分:5)
简答:我建议创建一个单独的类,其中包含有关实际String
和提升(int
)的信息。如果您假设以下内容:
public class BoostString {
int boost;
String str;
public BoostString(int boost, String str) {
this.boost = boost;
this.str = str;
}
}
然后,您可以使用Comparator
对数组进行排序,它对Java 8 Streaming API的效果特别好。
String[] strings = {"string1", "string2", "string3"};
int[] boosts = {40, 32, 34};
final String[] sorted = IntStream.range(0, boosts.length)
.mapToObj(i -> new BoostString(boosts[i], strings[i])) // Create the instance
.sorted(Comparator.comparingInt(b -> b.boost)) // Sort using a Comparator
.map(b -> b.str) // Map it back to a string
.toArray(String[]::new); // And return an array
上面示例中的Comparator
是使用Comparator.comparingInt
方法创建的,这是使用Java 8为int创建Comparator
的便捷方式。
说明:通常在比较Java中的对象时,您可以使用其中一个内置排序函数,例如Collections.sort
,您可以在其中提供自己的Comparator
。 Comparator
界面很简单,如下所示:
public interface Comparator<T> {
int compare(T o1, T o2);
// Other default methods for Java 8
}
返回值的类型为int
,并描述为like this in the JavaDoc:
返回负整数,零或正整数,因为第一个参数小于,等于或大于第二个参数。
当您对String
或int
(或实际Integer
s)进行排序时,这是开箱即用的,因为它们是Comparable
- 它们类似于有一个内置的自然排序,对于String
这是按字母顺序排列的,对于Integers
,它按升序排序(Comparable
为String
)。< / p>
另外,如果您使用的是第三方库,还有其他“对”或“元组”实现可用。您无需创建int
和{{1}}自己的“对”。一个例子是来自the JavaDoc的Pair类。
答案 2 :(得分:2)
您可以在旧式Java中执行类似于JS示例的操作(但我建议您在@wassgren建议的对象中将数据连接在一起):
import java.util.*;
public class WeightSort {
public static void main(String[] args) {
String[] strings = new String[]{"string1", "string2", "string3"};
final int[] weights = new int[]{40, 32, 34};
final List<String> stringList = Arrays.asList(strings);
List<String> sortedCopy = new ArrayList<String>(stringList);
Collections.sort(sortedCopy, new Comparator<String>(){
public int compare(String left, String right) {
return weights[stringList.indexOf(left)] - weights[stringList.indexOf(right)];
}
});
System.out.println(sortedCopy);
}
}
答案 3 :(得分:1)
我使用Comparator接口解决了这个问题。
import java.util.Comparator;
import java.util.Collections;
import java.util.List;
import java.util.Arrays;
public class ComparatorDemo {
public static void main(String[] args) {
List<Area> metaData = Arrays.asList(
new Area("Joe", 24),
new Area("Pete", 18),
new Area("Chris", 21),
new Area("Rose",21)
);
Collections.sort(metaData, new ResultComparator());
for(int i =0 ;metaData.size()>i;i++)
System.out.println(metaData.get(i).output);
}
}
class ResultComparator implements Comparator<Area> {
@Override
public int compare(Area a, Area b) {
return a.result < b.result ? -1 : a.result == b.result ? 0 : 1;
}
}
class Area{
String output;
int result;
Area(String n, int a) {
output = n;
result = a;
}
}
答案 4 :(得分:0)
如果您只构建用于此排序的数组B,则可以推迟在A的compareTo()中计算它的值。换句话说,仅在排序期间的比较中计算字符串的权重。
答案 5 :(得分:0)
package com.appkart.array;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class SortExample {
Map<String, Integer> map = new HashMap<String, Integer>();
Map<String, Integer> treemap = new TreeMap<String, Integer>(
new MyComparator(map));
public void addValueInMapAndSort() {
map.put("string1", 40);
map.put("string2", 32);
map.put("string3", 34);
System.out.println(map);
treemap.putAll(map);
System.out.println(treemap);
}
class MyComparator implements Comparator<String> {
Map<String, Integer> map;
public MyComparator(Map<String, Integer> map) {
this.map = map;
}
@Override
public int compare(String o1, String o2) {
if (map.get(o1) >= map.get(o2)) {
return 1;
} else {
return -1;
}
}
}
public static void main(String[] args) {
SortExample example = new SortExample();
example.addValueInMapAndSort();
}
}
使用Comparator根据值进行排序。
答案 6 :(得分:0)
我遇到了类似的问题,并通过编码排序算法来解决它,该算法对一系列度量进行排序,并在对象数组中进行相同的交换。这是代码,有测试,祝福和没有承诺:
package other;
import java.util.Arrays;
import java.util.Random;
/**
* Sorts an array of objects (<code>bags</code>) by a separate array of doubles (<code>measures</code>).
* It sorts into ascending order.
* <p>
* The <code>results</code> array is always a new array.
* <p>
* The algorithm used:<ul>
* <li> Is (I believe) a merge-sort, which would mean it is stable. (I haven't tested this.)
* <li> Efficiently exploits already ordered subsequences.
* <li> Requires the allocation of eight arrays: four of the baggage type, four of doubles, each the length of the original data.
* </ul>
* <p>
* A <code>NaN</code> in the <code>measures</code> - I haven't thought about that, and don't want to.
* <p>
* There is test code at the end of the class.
*/
public class SortBaggageByDouble {
public final Object [] results ;
protected final int length ;
public SortBaggageByDouble(Object[] bags, double[] measures) {
this.length = bags.length;
if (bags.length!=measures.length) throw new IllegalArgumentException("Mismatched lengths: payload array "+bags.length+", measures array "+measures.length);
this.results = new Object[length];
Object [] bagsA = new Object[length] ;
Object [] bagsB = new Object[length] ;
Object [] bagsC = new Object[length] ;
Object [] bagsD = new Object[length] ;
double [] measuresA = new double[length] ;
double [] measuresB = new double[length] ;
double [] measuresC = new double[length] ;
double [] measuresD = new double[length] ;
System.arraycopy(bags, 0, bagsA, 0, length);
System.arraycopy(measures, 0, measuresA, 0, length);
munge(length, 0, bagsA, bagsB, bagsC, bagsD, measuresA, measuresB, measuresC, measuresD);
}
private void munge(int inLengthA, int inLengthB, Object[] inBagsA, Object[] inBagsB, Object[] outBagsC, Object[] outBagsD, double[] inMeasuresA, double[] inMeasuresB, double[] outMeasuresC, double[] outMeasuresD) {
int outLengthC = 0 ;
int outLengthD = 0 ;
int cursorA = 0 ;
int cursorB = 0 ;
boolean toC = true ;
while(outLengthC+outLengthD<length) {
boolean fromA ;
if (cursorA>=inLengthA) {
fromA = false ;
} else if (cursorB>=inLengthB) {
fromA = true ;
} else {
fromA = inMeasuresA[cursorA] <= inMeasuresB[cursorB] ;
}
double tmpMeasure = fromA ? inMeasuresA[cursorA] : inMeasuresB[cursorB] ;
Object tmpBag = fromA ? inBagsA[cursorA] : inBagsB[cursorB] ;
if (fromA) cursorA ++ ; else cursorB ++ ;
if (toC) {
if (outLengthC==0 || (outMeasuresC[outLengthC-1]<=tmpMeasure)) {
outMeasuresC[outLengthC] = tmpMeasure ;
outBagsC[outLengthC] = tmpBag ;
outLengthC ++ ;
} else {
toC = false ;
outMeasuresD[outLengthD] = tmpMeasure ;
outBagsD[outLengthD] = tmpBag ;
outLengthD ++ ;
}
} else {
if (outLengthD==0 || (outMeasuresD[outLengthD-1]<=tmpMeasure)) {
outMeasuresD[outLengthD] = tmpMeasure ;
outBagsD[outLengthD] = tmpBag ;
outLengthD ++ ;
} else {
toC = true ;
outMeasuresC[outLengthC] = tmpMeasure ;
outBagsC[outLengthC] = tmpBag ;
outLengthC ++ ;
}
}
}
if (outLengthC==length) {
System.arraycopy(outBagsC, 0, results, 0, length);
} else {
munge(outLengthC, outLengthD, outBagsC, outBagsD, inBagsA, inBagsB, outMeasuresC, outMeasuresD, inMeasuresA, inMeasuresB);
}
}
/**
* Subclass to sort strings, with a result object <code>sortedStrings</code> which is of a useful type.
*/
public static class Strings extends SortBaggageByDouble {
public final String [] sortedStrings ;
public Strings(String[] in, double[] measures) {
super(in, measures);
this.sortedStrings = new String[results.length];
for (int i=0 ; i<results.length ; i++) sortedStrings[i] = (String) results[i] ;
}
}
/**
* Tests sorting - assumes there are no duplicates among the measures.
*/
private static class NoDuplicatesTest {
private NoDuplicatesTest(String[] shuffledStrings, double[] shuffledMeasures, String[] expectedStrings) {
SortBaggageByDouble.Strings sorter = new SortBaggageByDouble.Strings(shuffledStrings, shuffledMeasures);
if (!Arrays.equals(expectedStrings, sorter.sortedStrings)) throw new RuntimeException("Test failed");
}
}
private static class MultiseedNoDuplicatesTest {
private MultiseedNoDuplicatesTest(String[] orderedStrings, double[] orderedMeasures, int[] seeds) {
int length = orderedStrings.length;
for (int seed : seeds) {
Random random = new Random(seed);
int [] shuffleIndices = new int[length] ;
for (int i=0 ; i<length ; i++) shuffleIndices[i] = i ;
for (int i=1 ; i<length ; i++) {
int j = random.nextInt(i+1); // 'j' is in the range 0..i, bounds inclusive.
int tmp = shuffleIndices[i];
shuffleIndices[i] = shuffleIndices[j] ;
shuffleIndices[j] = tmp ;
}
String[] shuffledStrings = new String[length];
double[] shuffledMeasures = new double[length];
for (int i=0 ; i<length ; i++) {
shuffledStrings[shuffleIndices[i]] = orderedStrings[i] ;
shuffledMeasures[shuffleIndices[i]] = orderedMeasures[i] ;
}
if (false && 0<length && length<8) {
System.out.println("shuffleIndices is "+ stringfor(shuffleIndices));
System.out.println("shuffledStrings is "+ stringfor(shuffledStrings));
System.out.println("shuffledMeasures is "+ stringfor(shuffledMeasures));
}
new NoDuplicatesTest(shuffledStrings, shuffledMeasures, orderedStrings);
}
}
}
private static class MultilengthMultiseedNoDuplicatesTest {
MultilengthMultiseedNoDuplicatesTest(int[] lengths, int[] seeds) {
for (int i=0 ; i<lengths.length ; i++) {
int length = lengths[i] ;
String[] orderedStrings = new String[length] ;
double[] orderedMeasures = new double[length] ;
for (int j=0 ; j<length ; j++) {
orderedStrings[j] = "_"+j+"_" ;
orderedMeasures[j] = j ;
}
if (false && 0<length && length<8) {
System.out.println("orderedStrings is "+ stringfor(orderedStrings));
System.out.println("orderedMeasures is "+ stringfor(orderedMeasures));
}
new MultiseedNoDuplicatesTest(orderedStrings, orderedMeasures, seeds);
}
}
}
public static class ClassTest {
ClassTest() {
new MultilengthMultiseedNoDuplicatesTest(new int[]{0}, new int[]{8543, 45125});
new MultilengthMultiseedNoDuplicatesTest(new int[]{1}, new int[]{8543, 45125});
new MultilengthMultiseedNoDuplicatesTest(new int[]{2}, new int[]{8543, 45125, 4545, 785413});
new MultilengthMultiseedNoDuplicatesTest(new int[]{3, 4, 5, 6, 7, 8, 9, 10}, new int[]{8543, 45125, 4545, 785413});
new MultilengthMultiseedNoDuplicatesTest(new int[]{50, 100, 1000}, new int[]{474854, 43233});
////// Passed! Bye bye.
System.out.println("Passed test suite "+this.getClass().getCanonicalName());
}
}
public static String stringfor(int[] array) {
StringBuilder sb = new StringBuilder();
build(sb, array);
return sb.toString();
}
public static void build(StringBuilder sb, int[] array) {
for (int i=0 ; i<array.length ; i++) {
if (sb.length()>0) sb.append(' ');
sb.append(array[i]);
}
}
public static String stringfor(double[] array) {
StringBuilder sb = new StringBuilder();
build(sb, array);
return sb.toString();
}
public static void build(StringBuilder sb, double[] array) {
for (int i=0 ; i<array.length ; i++) {
if (sb.length()>0) sb.append(' ');
sb.append(array[i]);
}
}
public static String stringfor(String[] labels) {
StringBuffer sb = new StringBuffer();
String sep = "" ;
for (int i=0 ; i<labels.length ; i++) {
sb.append(sep);
String label = labels[i] ;
sb.append(label!=null ? label : "null");
sep = ", " ;
}
return sb.toString();
}
}
答案 7 :(得分:0)
可能不完全是那种情况,但对于那些寻找答案如何根据另一个排序一个String数组的人:
// Array of values, in a order of sorting
static final Map<String, Integer> ROUNDS_SORT = new HashMap<String, Integer>();
static {
ROUNDS_SORT.put("f", 0);
ROUNDS_SORT.put("s", 1);
ROUNDS_SORT.put("q", 2);
ROUNDS_SORT.put("r16", 3);
ROUNDS_SORT.put("r32", 4);
ROUNDS_SORT.put("r64", 5);
}
// Your array to be sorted
static ArrayList<String> rounds = new ArrayList<String>() {{
add("f");
add("q");
add("q");
add("r16");
add("f");
}};
// implement
public List<String> getRoundsSorted() {
Collections.sort(rounds, new Comparator<String>() {
@Override
public int compare(String p1, String p2) {
return Integer.valueOf(ROUNDS_SORT.get(p1)).compareTo(Integer.valueOf(ROUNDS_SORT.get(p2)));
}
});
return rounds;
}
答案 8 :(得分:0)
在Java中,您需要具有两个数组,一个要排序的副本和要排序的数组。
有lambda:
String[] strings = new String[]{"string1", "string2", "string3", "string4"};
final int[] ints = new int[]{100, 88, 92, 98};
final List<String> stringListCopy = Arrays.asList(strings);
ArrayList<String> sortedList = new ArrayList(stringListCopy);
Collections.sort(sortedList, (left, right) -> ints[stringListCopy.indexOf(left)] - ints[stringListCopy.indexOf(right)]);
或使用比较器:
String[] strings = new String[]{"string1", "string2", "string3", "string4"};
final int[] ints = new int[]{100, 92, 88, 98};
final List<String> stringListCopy = Arrays.asList(strings);
ArrayList<String> sortedList = new ArrayList(stringListCopy);
Collections.sort(sortedList, Comparator.comparing(s -> ints[stringListCopy.indexOf(s)]));
答案 9 :(得分:-1)
创建一个TreeMap<Integer, List<ObjectTypeFromA>>
,其中地图键是B中的值,地图值是A中的值(使用列表允许重复键)。根据定义,它将按B的顺序排序。
public static void main(String[] args) {
String[] strings = { "string1", "string2", "string3", "string4" };
int[] ints = { 40, 32, 32, 34 };
System.out.println(Arrays.toString(getSortedStringArray(strings, ints)));
}
public static String[] getSortedStringArray(String[] strings, int[] order) {
Map<Integer, List<String>> map = new TreeMap<>();
for (int i = 0; i < strings.length; i++) {
if (!map.containsKey(order[i])) {
map.put(order[i], new LinkedList<String>());
}
map.get(order[i]).add(strings[i]);
}
String[] ret = new String[strings.length];
int i = 0;
for (Map.Entry<Integer, List<String>> mapEntry : map.entrySet()) {
for (String s : mapEntry.getValue()) {
ret[i++] = s;
}
}
return ret;
}