通过mapsOrder数组确定下一张地图

时间:2019-04-19 00:07:41

标签: javascript arrays algorithm

我有对象的mapsOrder数组和mapsData数组:

let mapsOrder = [1,2,1,3];
let mapData = [
  {
    id: 1,
    gates: [
      {
        toId: 2,
        coords: {
          x: 2,
          y: 42
        }
      },
      {
        toId: 3,
        coords: {
          x: 9,
          y: 4
        }
      }
    ]
  },
  {
    id: 2,
    gates: [
      {
        toId: 1,
        coords: {
          x: 6,
          y: 5
        }
      }
    ]
  },
  {
    id: 3,
    gates: [
      {
        toId: 1,
        coords: {
          x: 2,
          y: 1
        }
      }
    ]
  }
]

我要实现的是基于mapsOrder的循环,其中mapsOrder数组值是mapData中的id,指定到下一张地图的门。

因此,我们有一个循环迭代4次,并在以下情况进行循环:

  • 循环索引是1当前映射是1下一个映射是2,到下一个的门是coords: { x: 2, y: 42 }
  • 循环索引是2当前地图是2下一个地图是1,到下一个的门是coords: { x: 6, y: 5 }
  • 循环索引是3当前地图是1下一个地图是3,到下一个的门是coords: { x: 9, y: 4 }
  • 循环索引是4当前地图是3下一个地图是1,到下一个的门是coords: { x: 2, y: 1 }

最后一次循环迭代将下一个映射视为mapsOrder数组的第一个。我尝试自己先确定下一张地图的ID来做到这一点,例如:

for(let i = 0; i < mapsOrder.length; i++) {
  let nextMap;
  let currentMapId = mapData[mapsOrder[i] - 1].id;
  if(i === mapsOrder.length - 1) {
    nextMap = mapData[0].id   
  } else {
    nextMapId = mapData[mapsOrder[i]].id;    
  }

  console.log('Current map is: ', currentMapId, 'and the next map id is:', nextMapId)
  console.log('break-----')

}

但是此控制台的ID不正确,demo

3 个答案:

答案 0 :(得分:5)

如果您不关心原始数组,则只需使用shift即可获得下一个门(shift将从阵列中删除该门,因此当对象位于再次遇到)。使用find从数组中查找对象:

let result = mapsOrder.map(id =>
    mapData.find(o => o.id == id).gates.shift().coords
);

在使用find之前,您可能想检查shift是否确实找到了东西,并且gates数组包含某些东西,这是一种更安全的方法:

let result = mapsOrder.map(id => {
    let obj = mapData.find(o => o.id == id);
    if(obj && obj.gates.length) {                  // if we found an object with the same id and that object still have gates
        return obj.gates.shift().coords;           // return the coords of the first gate and remove the gate from the array
    }                                              // otherwise, throw an error or something
});

不可更改:

我们将使用一个对象来跟踪shift数组中的门索引,而不是使用上一个示例中的gates

let nextGateIndex = Object.create(null);                             // create a prototypeless object to track the next gate index for each object
let result = mapsOrder.map(id => {
    let obj = mapData.find(o => o.id == id);
    let index;
    if(nextGateIndex[id] == undefined) {
        index = 0;
    } else {
        index = nextGateIndex[id] + 1;
    }
    nextGateIndex[id] = index;
    if(obj && index < obj.gates.length) {
        return obj.gates[index].coords;
    }                                                                // throw error or something
});

答案 1 :(得分:2)

如果按照您的描述,您的循环应类似于。似乎您想使用idtoId但要使用数组索引。用对象替换数组是一个好主意。

official repo

for(let i = 0; i < mapsOrder.length; i++) {
  let nextMap;
  let currentMapId = mapsOrder[i];
  if(i === mapsOrder.length - 1) {
    nextMapId = mapsOrder[0]   
  } else {
    nextMapId = mapsOrder[i + 1];    
  }
  let filteredMapData = mapData.filter(f => f.id == currentMapId);
  let filteredGates = filteredMapData.length > 0 ? filteredMapData[0].gates.filter(f => f.toId == nextMapId) : [];

  console.log('Current map is: ', currentMapId, 'and the next map id is:', nextMapId, 'gates:', filteredGates.length == 0 ? "no gates": filteredGates[0].coords)
  console.log('break----')

}

答案 2 :(得分:0)

我建议对JavaScript数组使用filter()函数,因为它非常快捷。此函数将返回一个数组,该数组将填充符合某些条件的原始项目(在这种情况下,对象具有所需的ID)。

for (let i = 0; i < mapsOrder.length; i++) {
    console.log(mapData.filter(mapDataItem => mapDataItem.id === mapsOrder[i]))
}