Сравнение двух массивов и получение сходства java

У меня есть два массива на моих собственных пользовательских объектах. Мне нужно найти количество сходства, чтобы оценить его. Пользователь отправит рецепт, который он приготовил, и программа должна оценить, насколько он соответствует исходному рецепту. Вот что я пробовал:

int increase = 100 / userRecipe.size();
for(int i = 0; i < userRecipe.size(); i++) {
    if (userRecipe.get(i).equals(bookRecipe.get(i))) {
         percent += increase;
    }
}

Однако основным недостатком этого решения является то, что теоретически эти два рецепта ниже имеют точность 0%, когда она должна быть 75%.

Item[] userRecipe = {milk, sugar, eggs, flour};
Item[] bookRecipe = {sugar, eggs, flour};

Однако это не работает, потому что два списка имеют разную длину, поэтому это не работает. Если кто-нибудь знает, как я должен подходить к этому, я был бы признателен. Вот проблемы

  • Список userRecipe может быть больше или меньше, чем список bookRecipe.
  • Смещение делает подсчет очков неточным

Я относительный новичок в java, поэтому, если кто-то не против дать мне хорошее решение, я был бы признателен! Спасибо.

В вашем примере, если бы у userRecipe был сахар с индексом 3 и мука с индексом 1, можно ли было бы ожидать, что точность будет 75% или она должна быть 25%, поскольку они вышли из строя?

Matt 22.03.2022 14:18

все равно будет 75%. Предположим, что списки, кстати, уже отсортированы.

Chspsa 22.03.2022 14:19

Как вы оцениваете того, кто переусердствует с рецептом. Включает в себя 5 предметов, но только 2 совпадают. Или включает 6 предметов, 4 из которых точно соответствуют рецепту.

WJS 22.03.2022 14:31

Вы должны терять процент за каждую ошибку, и да, это ошибка, так что процент.

Chspsa 22.03.2022 14:33

Итак, на мой вопрос, это будет 40% (2 из 5) и (66% 4 из 6)?

WJS 22.03.2022 14:35

Какими будут проценты для двух пользовательских рецептов по одному ингредиенту в каждом. [eggs] для одного и [milk] для другого.

WJS 22.03.2022 16:11

0% для [яиц] и [молока]. Также да для других q.

Chspsa 22.03.2022 16:15

Просто чтобы быть уверенным, прежде чем принять мой ответ, пожалуйста, проверьте мои проценты.

WJS 22.03.2022 16:18

Да, это дает результаты, которые я ожидал. Благодарю вас!

Chspsa 22.03.2022 16:21
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
9
68
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Предполагая, что списки отсортированы, для оптимального решения этой проблемы (без выполнения за время O (n ^ 2)) это классическая проблема управлять двумя указателями.

int increase = 100 / userRecipe.size();
int userIndex = 0;
int bookIndex = 0;
while (bookIndex < boockRecipe.size() && userIndex < userRecipe.size()) {
    if (userRecipe.get(userIndex).equals(bookRecipe.get(bookIndex))) {
        percentage += increase;
        bookIndex++;
    }
    userIndex++;
}

Это будет перебирать только каждый список однажды.

Ответ принят как подходящий

Вот мой взгляд на это.

  • используйте набор для хранения ингредиентов рецепта.
  • затем просто транслируйте каждое представление и получайте количество правильных ингредиентов.
  • затем вычислите процент на основе большего количества отправленных ингредиентов и количества рецептов (чтобы наказать за превышение указания)

Это работает независимо от порядка ингредиентов и работает в линейном времени для каждого пользователя из-за использования набора для хранения рецепта.

Set<String> bookRecipe = Set.of("sugar", "eggs", "flour");
double ingredientCount = bookRecipe.size();

List<List<String>> entries = List.of(List.of("milk", "sugar"),
        List.of("milk", "sugar", "eggs", "flour"),
        List.of("milk", "sugar", "eggs", "flour", "beer"),
        List.of("milk", "sugar", "whiskey", "paint"),
        List.of("milk", "sugar", "eggs", "beer", "hay"),
        List.of("milk", "beer", "hay"),
        List.of("milk", "sugar", "eggs", "beer", "hay",
                "orange juice"));

System.out.println("Recipe: " + bookRecipe + "\n");
for (List<String> submission : entries) {
    long correct = submission.stream()
            .filter(ingredient -> bookRecipe.contains(ingredient))
            .count();
    
    double percentage = correct
            / Math.max(ingredientCount, submission.size());
    
    System.out.printf("%3d%% - %s%n",
            (int) (percentage * 100), submission);
}

отпечатки

Recipe: [eggs, flour, sugar]

 33% - [milk, sugar]
 33% - [eggs]
  0% - [milk]
 75% - [milk, sugar, eggs, flour]
 60% - [milk, sugar, eggs, flour, beer]
 25% - [milk, sugar, whiskey, paint]
 40% - [milk, sugar, eggs, beer, hay]
  0% - [milk, beer, hay]
  0% - [beer, chips, salsa]
 33% - [milk, sugar, eggs, beer, hay, orange juice]

Я думаю, вы имеете в виду что-то вроде этого.

public static void main(String[] args) {





    String[] s1 = {"A", "B", "D"};//userRecipe
    String[] s2 = {"A", "B", "C","D","E"};//bookRecipe

    int percent=0;

    int largerCount=s1.length>s2.length ? s1.length:s2.length;
    int smallerCount=s1.length<s2.length ? s1.length:s2.length;
    String[] largeArr =s1.length>s2.length ?s1:s2;
    String[] smallerArr =s1.length<s2.length ?s1:s2;

    for(String x:largeArr)
        for (String y:smallerArr) {
            if (x==y) percent++;
        }

    System.out.println((percent*100)/largerCount+"%");

}

Другие вопросы по теме