Home > Blockchain >  Adding values to Map from a File
Adding values to Map from a File

Time:03-29

I want to iterate through a file that has key/value pairs and put them into a Map.

The file contains values like so:

forward 5
up 4
down 3
down 6
forward 4
...

Here is my code:

       private static void depthPosition() throws IOException {

        BufferedReader bufferedReader = new BufferedReader(new FileReader("/Users/WorkAcc/Desktop/file.txt"));
        String lines;
        Map<String, Integer> instructions = new HashMap<>();
        String [] pair;

        while ((lines = bufferedReader.readLine()) != null) {
           pair = lines.split(" ");
           instructions.put(pair[0], Integer.valueOf(pair[1]));
        }
        System.out.println(instructions);
    }
}

The problem I am having is that the Map called instructions is not adding new values from the file, it stops at size 3, not sure why. Would appreciate some help here. Thanks!

CodePudding user response:

This is an example of how you can calculate what you indicate in the comments.

public void depthPosition() throws IOException {
    int value = 5;
    List<Instruction> instructions = readInstructionsFromFile("/Users/WorkAcc/Desktop/file.txt");
    int result = calculateDepthPosition(instructions, value);
    System.out.println("result is: " result);
}

private List<Instruction> readInstructionsFromFile(String filePath) throws IOException {
    BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
    String line;
    Instruction instruction;
    List<Instruction> instructions = new ArrayList<>();
    String[] pair;

    while ((line = bufferedReader.readLine()) != null) {
        pair = line.split(" ");
        instruction = new Instruction(pair[0], Integer.valueOf(pair[1]));
        instructions.add(instruction);
    }
    return instructions;
}

private int calculateDepthPosition(List<Instruction> instructions, int value){
    int nextValue = value;
    int result = value;
    for (Instruction instruction : instructions) {
        nextValue = instruction.apply(nextValue);
        result = Math.min(result, nextValue);
    }
    return result;
}

public static class Instruction {

    private String type;
    private int amount;

    public Instruction(String type, int amount) {
        this.type = type;
        this.amount = amount;
    }

    public int apply(int value) {
        switch (type) {
            case "forward":
                return value   amount;
            case "down":
                return value - amount;
            case "up":
                return value ?? amount;
            default:
                return value;
        }
    }
}

CodePudding user response:

As was mentioned in the comments, duplicate keys are not permitted in maps.

If you want to read in those strings and maintain order (which would seem likely), you can do it like this.

  • create a record (immutable class) to hold the direction and amount. A regular class could also be used.
  • instantiate a Scanner to read the file (I am reading from a String for demo purposes).
  • create a List to hold the records. In this case an ArrayList
  • then iterate over the file as follows.
String s  = "forward 5\n up 4\n down 3\n down 6\n forward 4\n";

record Info(String direction, int amount){
    @Override
    public String toString() {
        return "[%s, %s]".formatted(direction, amount);
    }
}
Scanner input = new Scanner(s);
List<Info> list = new ArrayList<>();

while(input.hasNextLine()) {
    list.add(new Info(input.next(), input.nextInt()));
    input.nextLine();  // consume end of line marker
} while(input.hasNextLine());

list.forEach(System.out::println);

prints

[forward, 5]
[up, 4]
[down, 3]
[down, 6]
[forward, 4]

You can also interate and get the individual values like so.

for (Info info : list) {
  System.out.println(info.direction()   " "   info.amount());
}

prints

forward 5
up 4
down 3
down 6
forward 4

Note: The above solution presumes each line is well defined and contains a String and an int per line, separate by one or more spaces. Otherwise, an exception would likely be thrown.

Updated

Once I store the above data, I want to read it in order and do calculations based on the first parameter eg if forward then I add to the number, if down then I subtract from the number etc.

Based on the above added comment you can do it like the following (you may have to adjust the commands somewhat to fit your file).

You can also achieve the following result by iterating of the list created above and processing each line in a switch statement.

  • create a map to hold the values.
  • use Files.lines to stream the lines for processing
  • using mapMulti to process each line.
    • first split into a two parts
    • capture the count and the direction
    • if the direction is down, convert to up and change the sign.
    • for positive directions, use as is. (Note. no counter direction given for forward
    • then create a Map entry and insert into the stream.
  • collect in a map, summing the values
Map<String,Integer> map = null;
try {
map = Files.lines(Path.of("f:/inputFile.txt"))
        .<Map.Entry<String,Integer>>mapMulti((str, consumer) -> {
            String[] arr = str.split("\\s ");
            int count = Integer.valueOf(arr[1]);
            Map.Entry<String, Integer> entry =
                    switch (arr[0]) {
                case "forward","up"-> Map.entry(arr[0],
                        count);
                case "down" -> Map.entry("up", -count);
                default -> Map.entry("up, 0); // innocuous entry.
            };
            consumer.accept(entry);
        }).collect(Collectors.toMap(Entry::getKey, Entry::getValue, Integer::sum));
                
} catch (Exception e) {
    e.printStackTrace();
}
map.entrySet().forEach(System.out::println);

prints (the positive directions are used as keys).

forward=9
up=-5
  • Related