Считать взвешенный график из текстового файла
Я должен создать взвешенный график из текстового файла. Ниже приведен пример того, как выглядит текстовый файл. Первый номер является идентификатором фактической железнодорожной станции. Второе число - это возможный пункт назначения, а после запятой - время в секундах, необходимое для путешествия. Третий номер - еще один возможный пункт назначения.
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);
}
Поскольку я не могу вернуться в текстовый файл, я не могу представить, как должно выглядеть правильное решение.
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,cost), мы итерируем splittedLine
от индекса 1 и далее. Для каждого ребра данных мы разделяем на основе "," (из вашего входного файла), тогда как splittedEdge[0]
будет идентификатором назначения и splittedEdge[1]
будет стоимость к этому месту назначения. Мы создаем Edge
с этой информацией и добавить, что Edge
к Node
объект.