Чтение взвешенного графика из текстового файла

Мне нужно создать взвешенный график из текстового файла. Ниже приведен пример того, как выглядит текстовый файл. Первое число - это идентификатор фактической железнодорожной станции. Второе число — это возможный пункт назначения, а после запятой — время в секундах, необходимое для поездки. Третий номер — еще один возможный пункт назначения.

060060101832 060063101842,78 060054104822,90
060054104822 060060101832,90 060057104812,90 060058101502,90 060054105611,66
060057104812 060054104822,90 060057102802,72 

Я хочу сохранить маршруты в ArrayList. Каждый объект маршрута должен выглядеть так:

Start: 060060101832 
Destination: 060063101842
Time: 78

Проблема в том, что мне нужно хранить несколько маршрутов для одного и того же начального местоположения. Как правильно прочитать строки с помощью сканера? Мой подход был таким:

while (routes.hasNext()) {
        routes.useDelimiter(",| |\\n");
        String start = routes.next();
        String dest= routes.next();
        String time= routes.next();
        Edge edge = new Edge(start, dest, time);
        edges.add(edge);
    }

Поскольку я не могу вернуться в текстовый файл, я не могу представить, как должно выглядеть правильное решение.


person Ray Ban    schedule 26.06.2017    source источник
comment
Если мой ответ помог вам, пожалуйста, примите его.   -  person luizfzs    schedule 27.06.2017


Ответы (1)


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

// Java 8
Node n;
Edge e;
String[] splittedLine;
String[] splittedEdge;
HashMap<String, Node> stationNumberToNode = new HashMap<>();
// if the file is not too large, you can read the file at once
List<String> lines = Files.readAllLines(new File("path/to/file.txt").getPath());
for(String line : lines){
  splittedLine = line.split(" ");
  if((n = stationNumberToNode.get(splittedLine[0]) == null){
    n = new Node(splittedLine[0]); // assuming your Node has a constructor that takes the station id
    stationNumberToNode.put(stationNumberToNode[0], n);
  }
  for(int i = 1; i < splittedLine.lenght; ++i){
    splittedEdge = splittedLine[i].split(",");
    e = new Edge(splittedEdge[0], splittedEdge[1]); // assuming your Edgehas a constructor that takes the destination station and the cost
    n.addEdge(e);
  }
}

Пояснение

Node n;
Edge e;
String[] splittedLine;
String[] splittedEdge;
HashMap<String, Node> stationNumberToNode = new HashMap<>();

В идеале вы должны всегда объявлять переменные вне циклов, чтобы избежать выделения новой памяти на каждой итерации. Таким образом, мы объявляем наши 5 переменных перед входом в цикл. HashMap используется здесь, чтобы покрыть случай, когда ваш ввод не всегда сгруппирован, и вам не нужно каждый раз выполнять поиск по списку.

List<String> lines = Files.readAllLines(new File("path/to/file.txt").getPath());

Прочитать все строки в файле сразу. В качестве альтернативы, как указано в вопросе, вы можете прочитать файл, используя Scanner, как в этом ответе. Однако вы должны изменить способ перебора строк.

splittedLine = line.split(" ");

Разбивает строку на « », так как ваш входной файл хорошо отформатирован.

if((n = stationNumberToNode.get(splittedLine[0]) == null){
  n = new Node(splittedLine[0]); // assuming your Node has a constructor that takes the station id
  stationNumberToNode.put(stationNumberToNode[0], n);
}

Проверяет, находится ли текущий узел уже на HashMap. Если да, то он будет сохранен в переменной n. В противном случае он создаст Node с текущим идентификатором и добавит его к нашему HashMap.

for(int i = 1; i < splittedLine.lenght; ++i){
  splittedEdge = splittedLine[i].split(",");
  e = new Edge(splittedEdge[0], splittedEdge[1]); // assuming your Edgehas a constructor that takes the destination station and the cost
  n.addEdge(e);
}

Поскольку все во входном файле — это станция назначения и ее стоимость (id, стоимость), мы повторяем splittedLine, начиная с индекса 1 и далее. Для каждого ребра данные мы разделяем на основе «,» (из вашего входного файла), тогда как splittedEdge[0] будет идентификатором пункта назначения, а splittedEdge[1] будет стоимостью этого пункта назначения. Мы создаем Edge с этой информацией и добавляем это Edge к объекту Node.

person luizfzs    schedule 26.06.2017