es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo mapear todas las palabras en la descripción de una película con los nombres de todas las películas que contengan esa palabra en su descripción de manera rápida?

Tengo una List películas, donde cada película tiene int id y String descripción.
Mi tarea es asignar cada palabra de todas las descripciones a los nombres de las películas que contienen la palabra en la descripción, tiene que ser algo así:
: <idPelícula11>, <idPelícula12>,..., <idPelículaN1> : <idPelícula21>, <idPelícula22>, ..., <idPelículaN2>
...

Lo hice utilizando Java Stream API:

“`java
private List<><string, string=””>> wordToFilmIds;

private void addWordsFromDescriptions(List films) {
for (Film film : films) {
String description = film.description();
String[] tokens = description.split(“[\p{IsPunctuation}\p{IsWhite_Space}]+”);
allWords.addAll(Arrays.stream(tokens).toList());
}

}

private void mapWordsToFilmIDs(List films) {
    wordToFilmIds = allWords.stream()
            .map(word -> Map.entry(word,
                    films.stream()
                            .filter(film -> film.description().contains(word))
                            .map(film -> String.valueOf(film.id()))
                            .collect(Collectors.joining(","))))
            .toList();
}


Pero el problema es que mi solución es demasiado lenta y tengo que trabajar con números grandes, el número de películas es de alrededor de 12 000 y las descripciones no son cortas. Además, no se me permite utilizar multi-threading.
¿Alguna idea de cómo puedo optimizarlo?
Actualmente, el programa no termina.

También intenté usar parallel streams, aún así no funcionaba.

</string,>

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como mencionaste que no se te permite usar el multi-threading, tienes opciones limitadas para la paralelización. Sin embargo, aún hay algunas formas en las que puedes optimizar el código.

    Un enfoque podría ser preprocesar los datos y crear un mapa de cada palabra a un conjunto de películas que contienen esa palabra. Puedes hacer esto mientras lees las descripciones, en lugar de recorrer todas las películas para cada palabra. Una vez que tengas este mapa, podrás generar fácilmente la salida deseada.

    Aquí tienes una implementación de ejemplo:

    private Map<string,></string,><integer>> wordToFilmIds;
    
    private void addWordsFromDescriptions(List<film> films) {
        wordToFilmIds = new HashMap<>();
        for (Film film : films) {
            String description = film.description();
            String[] tokens = description.split("[\\p{IsPunctuation}\\p{IsWhite_Space}]+");
            for (String token : tokens) {
                wordToFilmIds.computeIfAbsent(token, k -> new HashSet<>()).add(film.id());
            }
        }
    }
    
    private void mapWordsToFilmIDs(List<film> films) {
        wordToFilmIds.entrySet().stream()
                .sorted(Map.Entry.comparingByKey())
                .forEach(entry -> {
                    String word = entry.getKey();
                    Set<integer> filmIds = entry.getValue();
                    String filmIdsStr = filmIds.stream().map(String::valueOf).collect(Collectors.joining(", "));
                    wordToFilmIdsList.add(Map.entry(word, filmIdsStr));
                });
    }
    

    En esta implementación, creamos un Map<string,></string,><integer>> que asigna cada palabra a un conjunto de IDs de películas que contienen esa palabra. Luego iteramos sobre todas las películas y sus descripciones, dividimos las descripciones en tokens y agregamos cada token al conjunto correspondiente en el mapa.

    Una vez que tenemos este mapa, podemos generar la salida deseada iterando sobre las entradas del mapa, ordenándolas por la palabra y creando una List de Map.Entry<string, string=""> que asigna cada palabra a la lista de IDs de películas separados por comas.

    Este enfoque debería ser mucho más rápido que la implementación original, ya que evita recorrer todas las películas para cada palabra. Sin embargo, dependiendo del tamaño de los datos, el uso de memoria puede convertirse en un problema si hay un gran número de palabras únicas. En ese caso, puede que desees considerar usar una base de datos o una estructura de datos más escalable para el mapa.</string,>

Comments are closed.