首页 > 解决方案 > while 循环为世界旅行创建一个数组

问题描述

我得到了以下代码,我试图在其中输出完整行程的结果。起点在Start,接下来的目的地将是 Start's坐标与其余城市之一(在本例中为多伦多)之间的最短距离。

在我的calcDirectRoute中,我只能输出Start>> Torontotrip 元素,因为我正在努力保持循环,其中数组的第二个元素是andTripList之间的最短距离,比方说,依此类推,直到没有更多的城市离开去旅行。TorontoLondon

在这种情况下,如何继续循环使用 while 循环?有人可以帮忙吗?

在我的示例中,以公里为单位的坐标/距离是虚构的。

const world = [
    [["Start"], [20, 20]],
    [["NY"], [29, 30]],
    [["London"], [24, 27]],
    [["Moscow"], [29, 32]],
    [["Toronto"], [20, 23]]
];

const calcDist2Points = function (p2, p1) {
    const r = 6371;
    let d, dLat, dLon;

    const lat2 = p2[1][0];
    const lon2 = p2[1][1];
    const lat1 = p1[1][0];
    const lon1 = p1[1][1];

    dLat = lat2 - lat1;
    dLon = lon2 - lon1;

    let a =
        Math.sin(dLat / 2) ** 2 +
        Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) ** 2;
    let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    d = r * c;

    return d; // distance in km
};



const calcDirectRoute = function (input) {

    let tripList = [];
    let distances = [];
    let tempStart = input[0];


    for (let i = 1; i < input.length; i++) {

        distances.push([tempStart[0], [tempStart[1][0], tempStart[1][1]], input[i][0], [input[i][1][0], input[i][1][1]], calcDist2Points(input[i], tempStart)]);

    }

    let short = distances[0];

    for (let i = 0; i < distances.length; i++) {
        for (let n = i + 1; n < distances.length; n++) {
            if (distances[n][4] < short[4])
                short = distances[n];
        }
    }

    // push EACH short result to tripList array

    tripList.push(short);


    tempStart = short.slice(2);


    return tripList;

}

console.log(calcDirectRoute(world));

标签: javascriptarraysloopswhile-loop

解决方案


我需要更新一点你的calcDist2Points()功能。我还更新了world对象的定义方式。

distance 属性表示到上一个城市的距离。

我相信我可以使用第三个库进行改进以使其更简单。现在我相信是功能性的。

我在这里包括一个使用 ramda 的实现

const formatOutput = (tripList) =>
  tripList.reduce((acc, { name, coordinates, distance }, index, arr) => {
    if (index <= 0) return [];
    const { name: prevName, coordinates: prevCoordinates } = arr[index - 1];
    const obj = [[prevName], prevCoordinates, [name], [...coordinates], distance];
    return [...acc, obj];
  }, []);

const compareByDistance = ({ distance: distanceA }, { distance: distanceB }) => distanceA - distanceB;

const getDistances = (origin, cities) =>
  Object.entries(cities)
    .map(([city, coordinates]) => ({ name: city, coordinates, distance: calcDist2Points(origin, coordinates) }))
    .sort(compareByDistance);

const world = [
  [["Start"], [20, 20]],
  [["NY"], [29, 30]],
  [["London"], [24, 27]],
  [["Moscow"], [29, 32]],
  [["Toronto"], [20, 23]],
];

const calcDist2Points = function (p2, p1) {
  const r = 6371;
  let d, dLat, dLon;

  const lat2 = p2[0];
  const lon2 = p2[1];
  const lat1 = p1[0];
  const lon1 = p1[1];

  dLat = lat2 - lat1;
  dLon = lon2 - lon1;

  let a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) ** 2;
  let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  d = r * c;

  return d; // distance in km
};

const calcDirectRoute = function (start, input) {
  const cities = input.reduce((cities, [[name], coordinates]) => ({ ...cities, [name]: coordinates }), []);
  const tripList = [];
  let coordinates = cities[start];

  do {
    const [closest] = getDistances(coordinates, cities);
    delete cities[closest.name];
    coordinates = closest.coordinates;
    tripList.push(closest);
  } while (Object.keys(cities).length !== 0);

  return formatOutput(tripList);
};

console.log(calcDirectRoute("Start", world));


推荐阅读