Reputation: 11
So I have 2 text files with sets of information containing names and numbers, is there a way I can separate the numbers, and add the numbers, while keeping the names in a new file?. Thanks
The first file looks like this
john-100
james-12
carlos-392
The second looks like this
john-4
james-38
carlos-8
So is there a way to get the final product to look like this in a new file?
john-104
james-50
carlos-400
Upvotes: 1
Views: 40
Reputation: 20914
The below code uses java's stream API. The code creates a stream of lines from each file. It reads the first file and creates a Map
where the map key is the name that appears in the file and the map value is the number (that appears in the file next to the name). Then it reads the second file and merges the data in the second file into the existing map.
In the original code (below), I forgot to handle the part where you want to write the resulting map to a file. I added it under the comment Added in edit
. I create a List
of strings from the map and write that list to a new file.
/* Required imports:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
*/
Path path1st = Paths.get("path-to-first-file");
Path path2nd = Paths.get("path-to-second-file");
Function<String, String> keyMapper = str -> {
String key = null;
if (str != null && str.indexOf('-') >= 0) {
String[] parts = str.split("-");
if (parts.length == 2) {
key = parts[0];
}
}
return key;
};
Function<String, Integer> valueMapper = str -> {
Integer value = null;
if (str != null && str.indexOf('-') >= 0) {
String[] parts = str.split("-");
if (parts.length == 2) {
try {
value = Integer.valueOf(parts[1]);
}
catch (NumberFormatException x) {
// Ignore.
}
}
}
return value == null ? Integer.valueOf(0) : value;
};
BinaryOperator<Integer> mergeFunction = (first, second) -> {
int one = first == null ? 0 : first.intValue();
int two = second == null ? 0 : second.intValue();
return Integer.valueOf(one + two);
};
try {
Map<String, Integer> theMap = Files.lines(path1st)
.collect(Collectors.toMap(keyMapper, valueMapper));
Map<String, Integer> totals = Files.lines(path2nd)
.collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, () -> theMap));
System.out.println(totals);
// Added in edit
List<String> lines = totals.entrySet()
.stream()
.map(entry -> String.format("%s-%s", entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
Files.write(Paths.get("path-to-new-file"),
lines,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE);
//
}
catch (IOException x) {
x.printStackTrace();
}
Running the above code, on the sample data you provided, outputs the following map contents:
{carlos=400, james=50, john=104}
Upvotes: 0
Reputation: 2058
I guess, there is definitely a way of doing that. But it doesn't seem correct to write code for you, so I just describe an algorythm, and it's up to you to implement it.
So you can first use https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#readAllLines-java.nio.file.Path- to read lines from file.
Then you can split each line per -
and put the result into a Map<String, Integer
using https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#compute-K-java.util.function.BiFunction-
Then just iterate on the map entries and build another List<String>
of the same structure with '%name%-%number%`.
And finally use https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#write-java.nio.file.Path-java.lang.Iterable-java.nio.charset.Charset-java.nio.file.OpenOption...- to write the List<String>
to a new file.
Upvotes: 2