1

I have three arrays

String[] persons = {"jack","james","hill","catnis","alphonso","aruba"};
int[] points = {1,1,2,3,4,5};
int[] money = {25,66,24,20,21,22};

The nth position in all three arrays belong to the same entity, for eg:-

persons[0] == points[0] == money[0] i.e jack has 1 point and 25 bucks.

I want to build a list that sorts person alphabetically(ascending) , if the starting letter is same , then it should check points(descending) and if those are same too then it must check the money(descending).

The final list after sorting should be {aruba , alphonso , catnis , hill , james , jack}.

0

4 Answers 4

3

So I think you want something like this:

public class Person {
   String name;
   int points;
   int money;

   public Person(String name, int points, int money) {
       this.name = name;
       this.points = points;
       this.money = money;
   }

   // getters
}

Then create a List<Person> with the data you have (e.g., new Person("jack", 1, 25)). And then sort them:

Collections.sort(persons, (person1, person2) -> {
    // could be written more concisely, but this should make things clear
    char letter1 = person1.getName().charAt(0);
    char letter2 = person2.getName().charAt(0);
    if (letter1 != letter2) {
        return letter1 - letter2;
    }
    int points1 = person1.getPoints();
    int points2 = person2.getPoints();
    if (points1 != points2) {
        return points2 - points1; // notice the order is reversed here
    }
    int money1 = person1.getMoney();
    int money2 = person2.getMoney();
    if (money1 != money2) {
        return money2 - money1;
    }
    return 0; // unless you want to do something fancy for tie-breaking
});

That will give you a sorted List<Person> according to your criteria.

Sign up to request clarification or add additional context in comments.

Comments

3

If you're up to something quick and dirty:

    Comparator<Integer> cName = (i, j) -> Character.compare( persons[i].charAt(0), persons[j].charAt(0));
    Comparator<Integer> cPoints = (i, j) -> Integer.compare( points[i], points[j]);
    Comparator<Integer> cMoney = (i, j) -> Integer.compare( money[i], money[j]);

    List<String> l = 
            IntStream.range(0, persons.length).boxed()
            .sorted( cName.thenComparing(cPoints.reversed()).thenComparing(cMoney.reversed()) )
            .map( i -> persons[i] )
            .collect(Collectors.toList());

    System.out.println(l);

The first 3 lines use lambdas to define comparators based on arrays indexes.

The following line uses streams:

  1. Create an int stream of indexes from 0 to persons.length-1
  2. Sort indexes of the stream based on the sequence of comparators
  3. Map sorted indexes to person names
  4. Collect it into a List

Ain't lambda and streams cool?

1 Comment

Technically, this answer is closest to what @CostLy10 was looking for.
2

If you can have a Person model:

final class Person {
  private final String name;

  private final int points;

  private final int money;

  public Person(final String name, final int points, final int money) {
    this.name = name;
    this.points = points;
    this.money = money;
  }

  // getters and setters (if you want)

  @Override
  public String toString() {
    final StringBuffer sb = new StringBuffer("Person {")
        .append("name=")
        .append(name)
        .append(", points=")
        .append(points)
        .append(", money=")
        .append(money)
        .append('}');
    return sb.toString();
  }
}

Then you could do something like this:

public static void main(final String... args) throws Exception {
  Person[] persons = new Person[6]; // Use a List (if you can)
  persons[0] = new Person("jack", 1, 25);
  persons[1] = new Person("james", 1, 66);
  persons[2] = new Person("hill", 2, 24);
  persons[3] = new Person("catnis", 3, 20);
  persons[4] = new Person("alphonso", 4, 21);
  persons[5] = new Person("aruba", 5, 22);
  System.out.printf("persons = %s%n%n", Arrays.toString(persons));
  System.out.printf("Person[0] = %s%n%n", persons[0]);
  Collections.sort(Arrays.asList(persons), (c1, c2) -> {
    final int charComp = Character.compare(c1.name.charAt(0), c2.name.charAt(0));
    if (0 == charComp) {
      final int pointsComp = Integer.compare(c2.points, c1.points);
      if (0 == pointsComp) { return Integer.compare(c2.money, c1.money); }
      return pointsComp;
    }
    return charComp;
  });
  // The collection was modified at this point because of the "sort"
  System.out.printf("persons = %s%n", Arrays.toString(persons));
}

Results:

persons = [Person {name=jack, points=1, money=25}, Person {name=james, points=1, money=66}, Person {name=hill, points=2, money=24}, Person {name=catnis, points=3, money=20}, Person {name=alphonso, points=4, money=21}, Person {name=aruba, points=5, money=22}]

Person[0] = Person {name=jack, points=1, money=25}

persons = [Person {name=aruba, points=5, money=22}, Person {name=alphonso, points=4, money=21}, Person {name=catnis, points=3, money=20}, Person {name=hill, points=2, money=24}, Person {name=james, points=1, money=66}, Person {name=jack, points=1, money=25}]


A more compact sort (but a little bit less efficient since you have to run all comparisons upfront):

Collections.sort(Arrays.asList(persons), (c1, c2) -> {
  final int names = Character.compare(c1.name.charAt(0), c2.name.charAt(0));
  final int points = Integer.compare(c2.points, c1.points);
  final int money = Integer.compare(c2.money, c1.money);
  return (0 == names) ? ((0 == points) ? money : points) : names;
});

Comments

0

Similar to EvanM's answer, you should group the three pieces of data into a single class.

public class Person {
   private String name;
   public String getName() { return name; }

   private int points;
   public int getPoints() { return points; }

   private int money;
   public int getMoney() { return money; }
}

Then you could sort them like so:

List<Person> persons = ...;

persons.sort(Comparator
    .comparing(p -> p.getName().charAt(0))
    .thenComparing(Comparator.comparing(Person::getPoints).reversed())
    .thenComparing(Comparator.comparing(Person::getMoney) .reversed())
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.