Почему мой 2D-массив JavaScript сортируется при нажатии на новый элемент?

#javascript #arrays

Вопрос:

Я пишу функцию, которая принимает данное слово в качестве параметра и возвращает положение его символов на основе этого 2D-массива:

 let keyboard = [
  ["a", "b", "c", "d", "e", "1", "2", "3"],
  ["f", "g", "h", "i", "j", "4", "5", "6"],
  ["k", "l", "m", "n", "o", "7", "8", "9"],
  ["p", "q", "r", "s", "t", ".", "@", "0"],
  ["u", "v", "w", "x", "y", "z", "_", "/"],
];

function tvRemote(word) {
  let arr = [...word];
  let position = [];
  for (let rows = 0; rows < keyboard.length; rows  ) {
    for (let cols = 0; cols < keyboard[rows].length; cols  ) {
      for (i of arr) {
        keyboard[rows][cols] === i ? position.push([i, rows, cols]) : null;
      }
    }
  }
  return position;
}
console.log( tvRemote("your") ); 

Я хотел бы получить позицию, чтобы выполнить некоторые вычисления, но при перемещении строк и столбцов в массив позиций, кажется, что возврат отсортирован.

Ожидаемый результат:

 [ [ 'y', 4, 4 ], [ 'o', 2, 4 ], [ 'u', 4, 0 ], [ 'r', 3, 2 ] ]
 

Что я получаю:

 [ [ 'o', 2, 4 ], [ 'r', 3, 2 ], [ 'u', 4, 0 ], [ 'y', 4, 4 ] ]
 

Кто-нибудь знает, что происходит? и если да, то как я могу предотвратить эту автоматическую сортировку?

Комментарии:

1. эм, вы идете не в порядке вашего слова, вы идете по порядку массивов, так что это не сортировка…. ваша логика неверна.

Ответ №1:

Проблема в том, что вы повторяете в порядке строк и столбцов, а не в порядке букв.

Внимательно прочитайте свой код; сначала вы устанавливаете rows = 0 cols = 0 , затем повторяете arr . В первом случае вы будете просматривать keyboard[0][0] и проверять, соответствует ли он каким-либо буквам arr , а затем, если да, нажимать на него position . Если ничего не совпадает, вы переходите к следующему столбцу, а затем, в конечном счете, к следующей строке.

Вместо этого вам нужно выполнить итерацию в порядке следования букв arr , например так:

 function tvRemote(word) {
  let arr = [...word];
  let position = [];
  for (i of arr) {
    for (let rows = 0; rows < keyboard.length; rows  ) {
      for (let cols = 0; cols < keyboard[rows].length; cols  ) {
        keyboard[rows][cols] === i ? position.push([i, rows, cols]) : null;
      }
    }
  }
  return position;

tvRemote("your");
 

Ответ №2:

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

Немного лучший подход-продолжить внешний цикл поиска.

 function tvRemote(word) {
  let arr = [...word];
  let position = [];
  outer: for (i of arr) {
    for (let rows = 0; rows < keyboard.length; rows  ) {
      for (let cols = 0; cols < keyboard[rows].length; cols  ) {
        if (keyboard[rows][cols] === i) {
          position.push([i, rows, cols]);
          continue outer;
        }
      }
    }
  }
  return position;
}

let keyboard = [["a", "b", "c", "d", "e", "1", "2", "3"], ["f", "g", "h", "i", "j", "4", "5", "6"], ["k", "l", "m", "n", "o", "7", "8", "9"], ["p", "q", "r", "s", "t", ".", "@", "0"], ["u", "v", "w", "x", "y", "z", "_", "/"]];

console.log(tvRemote("your")); 

Быстрый подход путем сбора всех индексов в объекте и отображения только нужного слова.

 function tvRemote(word) {
    return Array.from(
        word,
        l => positions[l]
    );
}

let keyboard = [["a", "b", "c", "d", "e", "1", "2", "3"], ["f", "g", "h", "i", "j", "4", "5", "6"], ["k", "l", "m", "n", "o", "7", "8", "9"], ["p", "q", "r", "s", "t", ".", "@", "0"], ["u", "v", "w", "x", "y", "z", "_", "/"]],
    positions = keyboard.reduce((r, a, i) => {
        a.forEach((l, j) => r[l] = [l, i, j]);
        return r;
    }, {})

console.log(tvRemote("your")); 

Комментарии:

1. Удивительно, спасибо за ответ, хотя я не совсем понимаю быстрый подход, перемещение итерации слова наверх решило мою проблему.

Ответ №3:

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

Помимо того, что вам нужно переместить цикл слов на верхний уровень, вам также не нужно использовать spread оператор. для этого можно перебирать строки.

 function tvRemote(word) {
  let position = [];
     for (let i of word) {
  for (let rows = 0; rows < keyboard.length; rows  ) {
    for (let cols = 0; cols < keyboard[rows].length; cols  ) {
 
        keyboard[rows][cols] === i ? position.push([i, rows, cols]) : null;
      }
    }
  }

  return position;
}
 

Комментарии:

1. Я только что обнаружил для, спасибо, что сообщили мне, что он может повторяться по строкам!