Страницы

Поиск по вопросам

суббота, 11 апреля 2020 г.

Заполнение массива значениями

#javascript #angularjs

                    
У меня есть пара массивов. Нужно занести определенные значения в нужные места. Здесь
даже не столько AngularJS нужен, сколько чистый JS: проход по массивам и т.д.

Мои массивы:


$scope.usersNew - массив пользователей с ответами на вопрос анкеты. Структура такая: 


id - идентификатор, понятно.
user - имя пользователя,
questions - массив ответов на вопросы. Его структура следующая: 


id вопроса,
name вопроса,
answer - собственно, ответ. По умолчанию записана строка "No answer".


$scope.anss - массив всех ответов из базы данных. Структура (та ее часть, которую
я использую):


sessionID - идентификатор сессии, аналог имени пользователя,


questionAnswer - структура, в которой хранится информация о вопросе и
ответе. Из нее беру: 


question - структура с информацией о вопросе. Я использую только поле id, 
answer - структура с информацией об ответе. Я использую поле text





Мой код:

// формирование массива пользователей с ответами
    // проход по пользователя
    for (var k = 0; k < $scope.usersNew.length; k++) {
        // проход по ответам
        for (var i = 0; i < $scope.anss.length; i++) {
            // принадлежность ответа пользователю
            if ($scope.anss[i].sessionID == $scope.usersNew[k].user) {
                // проход по ответам пользователя
                for (var j = 0; j < $scope.usersNew[k].questions.length; j++) {
                    // соответствие ответов по id вопроса
                    if ($scope.usersNew[k].questions[j].id ==
                        $scope.anss[i].questionAnswer.question.id) {
                        // присвоение ответа пользователю
                        $scope.usersNew[k].questions[j].answer =
                            $scope.anss[i].questionAnswer.answer.text;
                        break; break;
                    }
                }
            }
        }
    }


Дебаггер показал, что в строке присвоения ответа пользователю программа записывает
этот ответ сразу всем пользователям, хотя пользователи вроде как перебираются в самом
верхнем for.

У меня появилась мысль: может, дело в том, как я заполняла первый массив usersNew?
Когда записывала в поля answer значение "No answer", это выглядело примерно так:

for (var i = 0; i < $scope.anss.length; i++) {
    var item = { id: "", user: "", questions: {} }
    item.id = $scope.anss[i].id;
    item.user = $scope.anss[i].sessionID;
    item.questions = $scope.arrForAns;
    users.push(item);
}


Где $scope.arrForAns - массив, созданный таким образом:

$scope.arrForAns = answers.questions;
// answers.questions - это массив объектов, который я достала из JSON, там уже есть
id и name
for (var i = 0; i < $scope.arrForAns.length; i++) {
    $scope.arrForAns[i].answer = "No answer";
}


Я вроде читала, уже не уверена где, что с присвоением массивов есть загвоздка: что
копируются не данные, а ссылки, и, возможно, в памяти лежит один несчастный массив
questions на всех пользователей, и он-то и терзается со всех сторон.
Или я ошибаюсь, и это я читала о чем-то другом.
    


Ответы

Ответ 1



Да. Для всего, кроме примитивных типов копируется ссылка. К примитивным типам относятся созданные без использования new числа, строки и bool'ы, а также null и undefined. PS: Не лень было такой вопрос задавать вместо того, чтобы погуглить про передачу по ссылке? гугл объяснил в чем дело, но его решение почему-то не помогает Не очень разобрался со всей структурой, но подозреваю, что это из-за того, что внутри массива тоже ссылки. Ангуляр позволяет сделать глубокую копию при помощи angular.copy: item.questions = angular.copy($scope.arrForAns);

Ответ 2



Хронический пример "Closures". Самый простой способ решения - поместить содержание внутренних for(){} на тот же уровень, где находится сам цикл, например: function closure1() { function binder1(x){ return function(){ return x; }; } var arr = [], i; for (i = 0; i <10; i++){ arr[i] = binder1(i); } return arr; } console.log(closure1()); Или заменить присвоение ответа пользователю на: // соответствие ответов по id вопроса if ($scope.usersNew[k].questions[j].id == $scope.anss[i].questionAnswer.question.id) { // присвоение ответа пользователю (function(k, j, i) { return function() { $scope.usersNew[k].questions[j].answer = $scope.anss[i].questionAnswer.answer.text; }; })(k, j, i) } Проверять, если честно, лень, но смысл в том, что вам надо создать ещё один контекст для хранения j, i и k.

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

Отправить комментарий