Потоковая операция двумерного массива - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь найти лучший средний балл из двухмерного массива:

String[][] scores = { { "Amit", "70" }, { "Arthit", "60" }, { "Peter", "60" }, { "Arthit", "100" } };

Вывод: 80 (оценка Артита (60 + 100) / 2)

До сих пор я решал эту проблему с помощью нижеследующего подхода, однако я ищу элегантное решение с потоком:

public static void main(String[] args) {
        String[][] scores = { { "Amit", "70" }, { "Arthit", "60" }, { "Peter", "60" }, { "Arthit", "100" } };

        int highestAvg = Integer.MIN_VALUE;
        Function<String[], Integer> function = new Function<String[], Integer>() {
            @Override
            public Integer apply(String[] t) {
                int sum = 0, count = 0;
                for (int i = 0; i < scores.length; i++) {
                    if (t[0].equals(scores[i][0])) {
                        count++;
                        sum += Integer.parseInt(scores[i][1]);
                    }
                }
                int avg = sum / count;
                return highestAvg < avg ? avg : highestAvg;
            }
        };
        System.out.println(Arrays.stream(scores).map(function).max((o1, o2) -> o1.compareTo(o2)).get());
    }

Не могли бы вы предложить, каков лучший подход для обработки двумерного массива с использованием потока?

Примечание: Я не ищу точное решение, просто ищу ваше ценное предложение.

Ответы [ 3 ]

0 голосов
/ 19 октября 2018

Я знаю, что ответ был отправлен и уже принят, но просто делюсь тем, что я нашел, пытаясь ответить на ваш вопрос.

Map<String, Double> collect = Arrays.stream(scores)
    .collect(Collectors.groupingBy(arr -> arr[0], 
             Collectors.averagingDouble(arr -> Integer.parseInt(arr[1]))));

Здесь key - это имя, а value - этосреднее его баллов.Теперь вы можете перебрать эту карту, чтобы найти наибольшее значение и, следовательно, индекс наибольшего ключа.

РЕДАКТИРОВАТЬ:

Чтобы найти максимальное значение из карты, используйте:

Entry<String, Double> entry = collect.entrySet().stream()
         .max(Map.Entry.comparingByValue(Comparator.comparingDouble(e -> e.doubleValue())))
         .get();
0 голосов
/ 19 октября 2018

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

Collection<Double> values = Arrays.stream(scores)
                .collect(groupingBy(a -> a[0], averagingInt(a -> Integer.parseInt(a[1]))))
                .values();

System.out.println(Collections.max(values));

Этот поток передается по многомерному массиву scores и использует коллектор groupingBy для накопленияэлементы объединяются в группы по именам, а затем averagingInt используется в качестве нижестоящего коллектора для получения средних значений, а затем, наконец, используется Collections.max(values) для получения наилучшего среднего балла.

Другой подход:

double bestAverage = 
       Arrays.stream(scores)
             .collect(groupingBy(a -> a[0], averagingInt(a -> Integer.parseInt(a[1]))))
             .values()
             .stream()
             .mapToDouble(Double::doubleValue)
             .max().getAsDouble();

System.out.println(bestAverage);

Обратите внимание, что оба вышеуказанных подхода приведут к исключению, если источник пуст, поэтому, если вы хотите обработать это, вы можете использовать isPresent или некоторые другие Необязательные методы как таковыеorElse и др.

Arrays.stream(scores)
      .collect(groupingBy(a -> a[0], averagingInt(a -> Integer.parseInt(a[1]))))
      .values()
      .stream()
      .mapToDouble(Double::doubleValue)
      .max().ifPresent(v -> ...);

импорт:

import java.util.stream.*;
import static java.util.stream.Collectors.*;
0 голосов
/ 19 октября 2018

Вы можете более широко использовать встроенные функции потока, включая усреднение и группирование коллекторы:

Stream.of(scores)
        .collect(
                Collectors.groupingBy(a -> a[0], 
                Collectors.averagingInt(a -> Integer.parseInt(a[1]))))
        .entrySet()
        .stream()
        .max(Entry.comparingByValue())
        .ifPresent(bestScore -> {
                String message = String.format("Best score is %s, by %s", bestScore.getValue(), bestScore.getKey());
                System.out.println(message);
        });

Какие отпечатки Best score is 80.0, by Arthit

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