【问题标题】:Empty Array is Returned Javascript返回空数组 Javascript
【发布时间】:2020-06-04 22:02:42
【问题描述】:

我是 JavaScript 新手,我正在为一个挑战编写一个函数,该函数接收一个表示停车位的数组数组,以及一个带有正在寻找停车位的车辆类型的字符串。对于每种类型的汽车,大写字母表示特定位置可用。 该函数必须返回一个数组,其中点的坐标为 [X, Y] 对。

这是我目前编写的代码:

const whereCanIPark = (spots, vehicle) => {
let tmp = [];
  for(let k=0; k<spots.length; k++){
    for(let j=0; j<spots[k].length ; j++){
      switch(vehicle){
        case 'regular': if(spots[k][j]==='R') tmp.push([k,j]); continue;
        case 'small': if(spots[k][j]==='S') tmp.push([k,j]); continue;
        case 'motorcycles': if(spots[k][j]=== 'M') tmp.push([k,j]); continue;
      }
    } 
  } 
  return tmp;
}

当我打印我的数组时,它是空的。任何人都可以帮助我吗?

编辑:这是测试用例:

const spots = [
      // COLUMNS ARE X
      //    0    1    2    3    4    5
          ['s', 's', 's', 'S', 'R', 'M'], // 0 ROWS ARE Y
          ['s', 'M', 's', 'S', 'R', 'M'], // 1
          ['s', 'M', 's', 'S', 'R', 'm'], // 2
          ['S', 'r', 's', 'm', 'R', 'M'], // 3
          ['S', 'r', 's', 'm', 'R', 'M'], // 4
          ['S', 'r', 'S', 'M', 'M', 'S'], // 5
      ]

      const vehicle = 'regular' // possible options are 'regular', 'small', or 'motorcycle'

输出应为 [4,0]

我的 tmp 数组当前打印:[]

【问题讨论】:

  • 既然要修改tmp的原始值,不应该是let而不是const吗?
  • 您介意打印spotsvehicle 数组吗?谢谢。
  • @MarceloF。他没有修改tmp 的引用,所以使用const 很好,他应该使用什么。他正在修改tmp内容
  • @MarceloF。当您添加到数组或对象时,您没有重新分配或重新声明常量,它已经被声明和分配,您只是添加到常量指向的“列表”中,所以它应该可以工作很好。
  • @Jamie 我打印了景点和车辆

标签: javascript arrays logic


【解决方案1】:

我做了几个假设:

  • 您的输出数组的顺序错误(您希望它在数组中的访问方式,即 [0,4] 而不是 [4,0])。如果不正确,只需交换数组中两项的顺序即可。
  • 您似乎想要第一个有效位置,而不是整个列表。如果这是真的,请在最后留下[0]。如果没有,您可以将其删除以获取完整列表。
  • 您提供的一组字母和车辆类型非常详尽,代表了您可以使用的所有可能的字符串。如果这不准确,您可能需要重新查看检查空间“有效性”的规则。

const whereCanIPark = (spots, vehicle) => {
  return spots.flatMap(
    (row, rowIdx) => spots[rowIdx].map(
      (val, colIdx) => val === vehicle[0].toUpperCase()
        ? [rowIdx, colIdx] : false, // Note: If you want the other order, just swap row/col in the array -- but this matches reality in their array position.
    )
  ).filter(Boolean)[0]; // Your question seems to imply you want "the first available space".
}


const spots = [
      // COLUMNS
      //    0    1    2    3    4    5
          ['s', 's', 's', 'S', 'R', 'M'], // 0 ROWS
          ['s', 'M', 's', 'S', 'R', 'M'], // 1
          ['s', 'M', 's', 'S', 'R', 'm'], // 2
          ['S', 'r', 's', 'm', 'R', 'M'], // 3
          ['S', 'r', 's', 'm', 'R', 'M'], // 4
          ['S', 'r', 'S', 'M', 'M', 'S'], // 5
      ];

console.log(
  whereCanIPark(spots, 'regular')
);

【讨论】:

    【解决方案2】:

    我不能发表评论,也不想被标记为答案。只是想帮忙。 所以,我们开始吧:

    我最好的猜测是你调用 whereCanIPark 的方式有问题。下面的代码只适合我。

        const spots = [
      // COLUMNS ARE X
      //    0    1    2    3    4    5
      ['s', 's', 's', 'S', 'R', 'M'], // 0 ROWS ARE Y
      ['s', 'M', 's', 'S', 'R', 'M'], // 1
      ['s', 'M', 's', 'S', 'R', 'm'], // 2
      ['S', 'r', 's', 'm', 'R', 'M'], // 3
      ['S', 'r', 's', 'm', 'R', 'M'], // 4
      ['S', 'r', 'S', 'M', 'M', 'S'], // 5
    ]
    
    const vehicle = 'regular';
    const tmp = [];
    for (let k = 0; k < spots.length; k++) {
      for (let j = 0; j < spots[k].length; j++) {
        switch (vehicle) {
          case 'regular': if (spots[k][j] === 'R') tmp.push([k, j]); continue;
          case 'small': if (spots[k][j] === 'S') tmp.push([k, j]); continue;
          case 'motorcycles': if (spots[k][j] === 'M') tmp.push([k, j]); continue;
        }
      }
    }
    console.error(tmp);
    

    还有一个建议:

    不要将 Loop 放入循环中 - 创建一个方法。

    方法必须做一件事,如果是做两件事 -> 再做一个方法。

    在您的代码中,我至少会使用 3 种不同的方法。

    它有助于提高可读性和一般的调试。

    代码中充满了魔法字符串 - 'regular','motorcycles' 。创建 3 个变量来表示这些变量。

    代码风格很重要。它会让你的生活变得更轻松。 然后,您可以检查每个方法的输出并确定错误的确切位置。

    找到你的错误后,检查一下:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

    如果你使用它,它会使代码总体上更漂亮。

    【讨论】:

    • 要进一步添加,请查看 JS Array.reduce 方法,这意味着您不需要定义 tmp 数组。
    【解决方案3】:

    你可以这样做

    const spots = [
          // COLUMNS ARE X
          //    0    1    2    3    4    5
              ['s', 's', 's', 'S', 'R', 'M'], // 0 ROWS ARE Y
              ['s', 'M', 's', 'S', 'R', 'M'], // 1
              ['s', 'M', 's', 'S', 'R', 'm'], // 2
              ['S', 'r', 's', 'm', 'R', 'M'], // 3
              ['S', 'r', 's', 'm', 'R', 'M'], // 4
              ['S', 'r', 'S', 'M', 'M', 'S'], // 5
          ]
    const vehicle = 'regular'  
    
    const whereCanIPark = (spots, vehicle) => 
      {
      let tmp    = []
        , letter = {regular: 'R', small:'S', motorcycles: 'M' }[vehicle]
        ;
      spots.forEach((e,x)=>
        {
        let y = -1
        while ((y = e.indexOf(letter,++y))>=0) tmp.push([x,y])
        });
      return tmp;
      }
    
    document.write( JSON.stringify ( whereCanIPark(spots, vehicle) ))

    你也可以这样做:

    const spots = 
            [ [ 's', 's', 's', 'S', 'R', 'M' ] 
            , [ 's', 'M', 's', 'S', 'R', 'M' ] 
            , [ 's', 'M', 's', 'S', 'R', 'm' ] 
            , [ 'S', 'r', 's', 'm', 'R', 'M' ] 
            , [ 'S', 'r', 's', 'm', 'R', 'M' ] 
            , [ 'S', 'r', 'S', 'M', 'M', 'S' ] 
            ] 
      ,   vehicle = 'regular' 
      ,   option  = { regular: 'R', small:'S', motorcycles: 'M' }
      ,   jojo = spots.reduce((a,c,x)=>
            {
            let y = -1
            while ((y=c.indexOf(option[vehicle],++y))>-1) a.push([x,y])
            return a
            },[])
    document.write ( JSON.stringify ( jojo ))

    【讨论】:

      【解决方案4】:
      const spots = [
        ['s', 's', 's', 'S', 'R', 'M'], // spots[0], spots[0][0] === 's', spots[0][3] === 'S', spots[0][5] === 'M'
        ['s', 'M', 's', 'S', 'R', 'M'], // spots[1]
        ['s', 'M', 's', 'S', 'R', 'm'], // spots[2]
        ['S', 'r', 's', 'm', 'R', 'M'], // spots[3]
        ['S', 'r', 's', 'm', 'R', 'M'], // spots[4]
        ['S', 'r', 'S', 'M', 'M', 'S'], // spots[5] and spots.length === 6
      ]
      
      const vehicle = 'regular' // possible options are 'regular', 'small', or 'motorcycle'
      
      const whereCanIPark = (spots, vehicle) => {
        let tmp = [];
        for (let k = 0; k < spots.length; k++) {
          for (let j = 0; j < spots[k].length; j++) {
            switch (vehicle) {
              case 'regular':
                if (spots[k][j] === 'R') tmp.push([k, j]);
                continue;
              case 'small':
                if (spots[k][j] === 'S') tmp.push([k, j]);
                continue;
              case 'motorcycles':
                if (spots[k][j] === 'M') tmp.push([k, j]);
                continue;
            }
          }
        }
        return tmp;
      }
      
      const output = whereCanIPark(spots, vehicle);
      
      console.log(output);
      

      输出: [[0, 4], [1, 4], [2, 4], [3, 4], [4, 4]]

      见: https://jsfiddle.net/uqygj65h/

      顺便说一句,“行”是“X”,即点的第一维。 “列”将是第二个维度,即点[行][列]。我已经编辑了你的 cmets 来展示这个。

      另一点 - 'm' 与 'M' 不同,即 'm' !== 'M'。如果您想忽略此案例,则可以使用if (spots[k][j].toUpperCase() === 'M')

      您使用Array.reduce编写的函数:

      const whereCanIPark = (spots, vehicle) =>
        spots.reduce((acc, level, levelIndex) => {
          level.forEach((space, spaceIndex) => {
            if (
              (vehicle === 'regular' && space.toUpperCase() === 'R') ||
              (vehicle === 'small' && space.toUpperCase() === 'S') ||
              (vehicle === 'motorcycles' && space.toUpperCase() === 'M')
            )
              acc.push([levelIndex, spaceIndex]);
          });
          return acc;
        }, []);
      

      你可以写得更简洁,但你应该能够看到 reduce 和 forEach 函数是如何工作的。

      额外的作业:

        if (
          (vehicle === 'regular' && space.toUpperCase() === 'R') ||
          (vehicle === 'small' && space.toUpperCase() === 'S') ||
          (vehicle === 'motorcycles' && space.toUpperCase() === 'M')
        )
      

      可以写成: if (vehicle[0].toUpperCase() === space.toUpperCase())

      还有一些作业,使用括号和逗号运算符,函数变为:

      const whereCanIPark = (spots, vehicle) =>
        spots.reduce((acc, level, levelIndex) =>
          (level.forEach((space, spaceIndex) => {
            if (vehicle[0].toUpperCase() === space.toUpperCase()) acc.push([levelIndex, spaceIndex]);
          }), acc), []);
      

      刚刚注意到您的大写数组项是故意的,将位置标记为可用。我应该更好地阅读你的问题。在这种情况下,您只需比较数组项值本身而不将其更改为大写:

      const whereCanIPark = (spots, vehicle) =>
        spots.reduce((acc, level, levelIndex) =>
          (level.forEach((space, spaceIndex) => {
            if (vehicle[0].toUpperCase() === space) acc.push([levelIndex, spaceIndex]);
          }), acc), []);
      

      祝你学习 JavaScript 好运。熟悉之后再看看 TypeScript,“You Don't Know JavaScript Yet”是一本不错的读物。

      【讨论】:

        猜你喜欢
        • 2021-12-16
        • 1970-01-01
        • 2020-09-03
        • 1970-01-01
        • 2016-06-29
        • 2020-05-14
        • 1970-01-01
        • 1970-01-01
        • 2021-11-13
        相关资源
        最近更新 更多