Как я могу сгруппировать список <Object>в другой список <Object>по некоторым атрибутам - PullRequest
0 голосов
/ 28 апреля 2019

Я пытаюсь сгруппировать List<Object>, который содержит

Exercice, type, User, passed, ..

Есть и другие, но они самые важные, дело в том, что я получаю длинный список, поэтому я хочу сгруппировать его по:

Type, User, NumberOfPassed, NumberOfFaileds

Например, у меня есть:

Exercice1, hand, Hans@gmail.com, true
Exercice2, hand, Hans@gmail.com, false
Exercice3, hand, Hans@gmail.com, false
Exercice4, hand, Hans@gmail.com, false
Exercice2, hand, Thiago@gmail.com, true
Exercice1, hand, Thiago@gmail.com, true

И вывод должен быть

Hand, Hans@gmail.com, 1/4
Hand, Thiago@gmail.com, 2/2

Ответы [ 3 ]

1 голос
/ 28 апреля 2019

Я думаю, вы могли бы создать этот объект, чтобы помочь вам решить это:

public class Result {
  private String type;
  private String email;
  private int numPassed;
  private Double total;

  public Result(String type, String email, boolean approved) {
      total = 1.0;
      this.type = type;
      this.email = email;
      this.numPassed = approved ? 1 : 0;
  }

  public void increase(boolean examResult){
      total++;
      if(examResult){
          numPassed++;
      }
  }

  public boolean isApproved(){
      return numPassed >= total / 2d;
  }

  public String getFraction(){
    return numPassed + "/" + total.intValue();
  }
}

И алгоритм объединения вашего списка должен быть таким:

private static List<Result> group(List<Input> yourList) {
    List<Result> result = new ArrayList<>();

    for (Input i : yourList) {
        String type = i.getType();
        String email = i.getEmail();
        boolean approved = i.isApproved();
        Result r = getIfExists(result, type, email);

        if(r != null){
            result.remove(r);
            r.increase(approved);
        } else{
            r = new Result(type, email, approved);
        }

        result.add(r);
    }

    return result;
}

private static Result getIfExists(List<Result> results, String type, String email) {
    Result result = null;
    boolean exit = false;
    for (int i = 0; i < results.size() && !exit; i++) {
        Result r = results.get(i);
        if (r.getType().equals(type) && r.getEmail().equals(email)) {
            result = r;
            exit = true;
        }
    }
    return result;
}

Этот код не будет компилироваться, так как он не реализует setter-getter, но его реализация будет работать.

1 голос
/ 29 апреля 2019

Учитывая, что ваш класс данных выглядит следующим образом:

data class UserData(
        val exercise: String,
        val type: String,
        val emailAddress: String,
        val passed: Boolean
)

Вы можете сначала сгруппировать по type и emailAddress, используя Pair в качестве ключа для полученной карты:

val groupingMap = l.groupBy{ it.type to it.emailAddress }

groupingMap будет иметь тип: Map<Pair<String, String>, List<UserData>>

После этого вы можете выполнить итерацию по этой карте, используя forEach, например:

resultMap.forEach { (groupKey, list) ->
    val numElements = list.count()
    val numTrueElements = list.count { it.passed }
    val (type, emailAddress) = groupKey
    println("$type, $emailAddress, $numTrueElements/$numElements")
}

Результат:

hand, Hans@gmail.com, 1/4
hand, Thiago@gmail.com, 2/2

Могут быть более подходящие типы для type и, может быть, даже exercise (зависит от варианта использования), но для примера я выбрал String.

0 голосов
/ 28 апреля 2019

Я думаю, что Вы можете использовать список> для группировки списка Объектов в другой список Объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...