многомерный массив indexOf не работает js

Я пытаюсь найти индекс числа в массиве 2d, но консоль выдает

Uncaught TypeError: block[((a * 10) + c)].indexOf не является функцией

Я думаю, что это как-то связано со способом доступа к элементу массива, но не могу найти проблему.

Вот код.

var block = [];
var temp;
var del;

for(var a = 0;a < 9;a++){
    for(var b = 0;b < 9;b++){
        temp = parseInt(prompt("enter element number " + b + " of row number " + a));
        console.log(temp);
        if(temp>0){
            block[a*10+b] = temp;
        }else{
            block[a*10+b] = [1,2,3,4,5,6,7,8,9];
        }
//      console.log(block[a*10+b]); 
    }
}
for(var a = 0;a < 9;a++){
    for(var b = 0;b < 9;b++){
        if(typeof(block[a][b]) == "number"){
            for(var c = 0;c < 9;c++){
                if(c != b){
                    del = block[a*10+c].indexOf(b);
                    block[a*10+c].splice(del,1);
                }
            }

        }

    }
}

person Ashot Tarumyan    schedule 12.11.2016    source источник
comment
Во-первых, я бы сделал: console.log(block[((a * 10) + c)]) чтобы посмотреть, что это такое. Но, более конкретно, ошибка, которую вы получаете, указывает на то, что значение, вероятно, является объектом, а объекты не имеют метода indexOf... Строки имеют, но у вас, вероятно, нет сохраненной строки. Кроме того, помните, что ВСЕ данные, возвращаемые из prompt, возвращаются в виде строки. Даже если число было введено.   -  person Scott Marcus    schedule 12.11.2016
comment
числа не имеют метода indexOf()   -  person dandavis    schedule 12.11.2016
comment
Вы не создаете многомерный массив, block — это просто массив. Первый цикл вставляет элементы с индексами от 0 до 99 так, как это можно сделать в одном цикле от 0 до 99. Только если вы введете отрицательное значение, элемент block будет массивом, вы скорее всего хочу typeof block[a][b] != "number". Но затем вы получаете доступ к block[a*10+c].   -  person RobG    schedule 12.11.2016
comment
Я создаю многомерный массив. Посмотрите на 12-ю строку. Всякий раз, когда ввод nan, он превращает * 10 + b элемент блока в массив   -  person Ashot Tarumyan    schedule 12.11.2016
comment
Я не знаю, поможет ли это, но я только что попытался заменить parseInt(prompt(".....")); на 5, и я не получил никаких ошибок.   -  person Motassem MK    schedule 13.11.2016
comment
Действительно, @AshotTarumyan, в этом случае это вложенный массив, но не тогда, когда ввод является допустимым числом. В этом случае вы назначаете этот номер, а не массив.   -  person trincot    schedule 13.11.2016


Ответы (2)


У вас есть смесь типов данных, назначенных массиву block. Когда пользователь вводит нечисловое значение, вы действительно назначаете вложенный массив одному из элементов block, но не так, когда пользователь вводит действительное число.

Из того, что я думаю, что вы делаете (игра в судоку?), это может иметь в виду: числа являются известными значениями в сетке, вложенные массивы представляют собой список значений, которые все еще возможны в этой конкретной ячейке.

Но затем во второй части вашего кода вы должны проверить, в каком из двух случаев вы находитесь, поскольку вы хотите удалить элементы массива только в том случае, если значение, на которое вы смотрите, действительно является массивом. Этот тест вы можете сделать с Array.isArray().

Есть также некоторые другие проблемы во второй части вашего скрипта:

  • Выражение block[a][b] не соответствует тому, как вы заполнили этот массив: оно должно быть block[a*10+b], чтобы быть непротиворечивым.
  • b в .indexOf(b) неверно: вы ищете не это значение, а block[a*10+b].
  • splice() всегда выполняется, даже если indexOf возвращает -1. Это приводит к нежелательному эффекту, так как если первый аргумент splice() отрицательный, индекс действительно отсчитывается с конца массива, и все равно элемент из массива удаляется. Этого не должно происходить: вы должны выполнять splice только в том случае, если результат indexOf неотрицательный.

Ниже я разместил рабочую версию, но, чтобы избежать почти бесконечных подсказок, я предоставил этот фрагмент с текстовым полем, где вы можете ввести полную сетку 9x9 за один раз, а затем нажать кнопку, чтобы начать выполнение вашего кода. :

document.querySelector('button').onclick = function () {
    var block = [];
    var temp;
    var del;
    var text = document.querySelector('textarea').value.replace(/\s+/g, '');
    for(var a = 0;a < 9;a++){
        for(var b = 0;b < 9;b++){
            temp = parseInt(text[a*9+b]); // <-- get char from text area
            if(temp>0){
                block[a*10+b] = temp;
            }else{
                block[a*10+b] = [1,2,3,4,5,6,7,8,9];
            }
        }
    }
    for(var a = 0;a < 9;a++){
        for(var b = 0;b < 9;b++){
            var num = block[a*10+b]; // <-- get content, fix the index issue
            if(typeof num == "number"){
                for(var c = 0;c < 9;c++){
                    if(c != b && Array.isArray(block[a*10+c])){ //<-- add array-test
                        del = block[a*10+c].indexOf(num); // <-- not b, but num
                        if (del > -1) // <-- only splice when found 
                            block[a*10+c].splice(del,1);
                    }
                }
            }
        }
    }
    document.querySelector('pre').textContent = 'block='+ JSON.stringify(block);
};
<textarea rows=9>
53..7....
6..195...
.98....6.
8...6...3
4..8.3..1
7...2...6
.6....28.
...419..5
....8..79
</textarea>
<button>Process</button>
<pre></pre>

Обратите внимание, что в block есть элементы, которые остаются null. Я полагаю, вы имели в виду это: когда вы умножаете a на 10 и сохраняете только 9 значений в «строке», всегда остается один индекс, который остается нетронутым.

person trincot    schedule 12.11.2016
comment
Большое спасибо! Я просто новичок в программировании, поэтому я сделал большие ошибки. И да, это решатель судоку. - person Ashot Tarumyan; 16.11.2016
comment
Добро пожаловать ;-) - person trincot; 17.11.2016

Я не просматривал ваш второй цикл for, но вы можете попробовать применить там ту же логику, что и в предоставленном фрагменте. Проблема в том, что вам нужно создать временный массив внутри внешнего цикла for по значениям a (но НЕ внутри внутреннего вложенного цикла for по значениям b). Затем внутри цикла for для значений b вам нужно что-то push добавить во временный массив (который я назвал temp). Затем вне цикла b for, но перед следующей итерацией a, поместите этот временный массив temp в массив block. Таким образом, вы создадите двумерный массив.

var block = [];
var del;

for(var a = 0; a < 9; a++) {
  let temp = [];
  for(var b = 0; b < 9; b++) {
    let num = parseInt(prompt(`Enter element ${b} of row ${a}:`));
    if (num > 0) {
      temp.push(num);
    } else {
      // block[a*10+b] = [1,2,3,4,5,6,7,8,9];
      temp.push(b);
    }
  }
  block.push(temp);
}

person IsenrichO    schedule 12.11.2016