Streams

0

Hej! Na podstawie zdania, które z pliku wejsciowego:
1 2 3 4 5
2 7 3 4 6
daje wynik pliku wyjściowego:
1+2+3+4+5=15
2+7+3+4+6=22
Muszę za pomocą strumieni - napisać całe zadanie w jak najmniejszej liczbie wierszy .W Jaki sposób użyć operacji mapy , która wewnątrz podzieli linię przez białe spacje i przekształci ją w strumień a potem użyje operacji zmniejszania , aby uzyskać liczby połączone z „+”, a następnie użyć tego samego jak powyżej, aby obliczyć sumę liczb i połączyć ją z powyższym ciągiem)?
Mój kod to:

public static void main(String[] args) throws IOException {
    Path path = Paths.get("src/main/resources/processedFile.txt");
    Files.lines(path)
            .filter(s -> s.matches("(\\d+).*"))
            .flatMap(l -> Arrays.stream(l.split(" "))).map(String::trim)
            .collect(Collectors.toCollection(LinkedList::new))
            .forEach(System.out::println);
}
0

Edit: Jak zauważył @Shalom w komentarzu dla dwóch takich samych inputów może wybuchnąć, także nie do końca super rozwiązanie.

Może coś takiego:

public static void main(String[] args) throws IOException {
    Path path = Paths.get("src/main/resources/processedFile.txt");
    Files.lines(path)
        .filter(s -> s.matches("(\\d+).*"))
        .collect(Collectors.toMap(str -> str.replaceAll(" ", "+"), str -> Arrays.stream(str.split(" ")).mapToInt(Integer::valueOf).sum()))
	.entrySet()
	.forEach((entry) -> System.out.println(entry.getKey() + "=" + entry.getValue()));
}
1

Skoro w jak najmniejszej ilości wierszy to pousuwałbym jeszcze entery z przed kropek :)

0
        Files.lines(Paths.get("inputs.txt"))
                .map(line -> Arrays.stream(line.split(" "))
                        .map(Integer::valueOf)
                        .collect(Collectors.toList())
                )
                .map(intsList -> intsList.stream()
                        .map(String::valueOf)
                        .collect(Collectors.joining("+"))
                        + "="
                        + intsList.stream().mapToInt(y -> y).sum()
                )
                .forEach(System.out::println);

Chyba nie da się elegancko tego zrobić bez operacji terminalnej w środku (to moje toList czy toMap u kolegi wyżej). Można by zrobić:

        Files.lines(Paths.get("inputs.txt"))
                .map(line -> Arrays.stream(line.split(" "))
                        .map(Integer::valueOf)
                )
                .map(intsStream -> {
                    AtomicInteger acc = new AtomicInteger();
                    return intsStream
                        .map(x->{acc.addAndGet(x); return x.toString();})
                        .collect(Collectors.joining("+"))
                        + "="
                        + acc.toString();}
                )
                .forEach(System.out::println);

i będzie single-pass (czytamy dane tylko raz), ale to rakulec ;D

1

Nieskromnie dodam że Files.lines powinno być w bloku try-with-resources (przynajmniej teoretycznie :D)

0

Ode mnie takie coś, jakoś fajnie to się chyba nie da

Files.lines(Paths.get("inputs.txt"))
                .map(Pattern.compile(" ")::split)
                .map(ls -> Arrays.stream(ls).collect(collectingAndThen(joining("+"), res -> String.format("%s=%d",res ,Arrays.stream(ls).mapToInt(Integer::parseInt).sum()))))
                .forEach(System.out::println);
0

A w jaki sposób zapisać to do nowego pliku? Próbowałam z kopią( jest inny sposób, bez przypisywania do zmiennej)?

public static void main(String[] args) {
    Path path = Paths.get("src/main/resources/processedFile.txt");
    Path newFile = Paths.get("src/main/resources/newFile.txt");
    try (OutputStream os = new FileOutputStream(newFile.toFile())) {
    Files.lines(path)
                .map(line -> Arrays.stream(line.split(" "))
                        .map(Integer::valueOf)
                        .collect(Collectors.toList()))
                .map(intsList -> intsList.stream()
                        .map(String::valueOf)
                        .collect(Collectors.joining("+"))
                        + "="
                        + intsList.stream().mapToInt(y -> y).sum())
                .forEach(System.out::println);

        Files.copy(newFile, os);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
0

o_O
Zamiast tego .forEach(System.out::println); użyj Files.write()
Strumienie da się przeglądać tylko raz, a forEach jest terminalne i po nim nie da się już nic zrobić. Jeśli chcesz zarówno wypisać na ekran jak i do pliku, to trzeba by zrobić forEach(naszaFunkcja) i w tej funkcji zrobić obie rzeczy, albo zapisać wynik do jakiejś listy.

0

A jeśli do forEach użyję PrintWriter( .forEach(printWriter::println); )? Tylko plik wyjściowy wciąż zostaje pusty.(przepraszam, że tyle pytam, ale od paru dni nie jestem wstanie znalezc nigdzie odpowiedzi)

    public static void main(String[] args) {

        String filePath = "src/main/resources/processedFile.txt";
        new FileProcessorOfStream().fileReader(filePath);
    }

    public void fileReader(String fileName) {

        try (Stream<String> streamReader = Files.lines(Paths.get(fileName));
             PrintWriter printWriter = new PrintWriter("newFile.txt")) {
            streamReader
                    .map(line -> Arrays.stream(line.split(" "))
                            .map(Integer::valueOf)
                            .collect(Collectors.toList()))
                    .map(intsList -> intsList.stream()
                            .map(String::valueOf)
                            .collect(Collectors.joining("+"))
                            + "="
                            + intsList.stream().mapToInt(y -> y).sum())
                    .forEach(printWriter::println);

        } catch (IOException e) {
            System.out.println("File not found");
            e.printStackTrace();
        }
    }
}
2

Tylko plik wyjściowy wciąż zostaje pusty

To znaczy że ćpiesz narkotyki albo patrzysz na zły plik. Bo kod działa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1