JS Невозможно создать многомерный массив

Я пытаюсь создать массив js с ключом = trener_id и значениями = выбранным идентификатором службы из отмеченных флажков.

Что бы я ни делал, массив создается, но также есть много пустых значений, которые сохраняются в массиве. Как этого избежать и, наконец, иметь чистый JS-массив с ключом trener_id и значениями только выбранных идентификаторов сервисов

Также возможно ли и как добавить подмассив, в котором к каждому выбранному значению услуги прикреплены Price customer и Price trener?

PHP-эквивалент желаемого формата массива:

$trener_services = array(1){
[13]=>
  array(2) {
[47]=>array(2){
['Price_customer']=>
string(5) "10.00",
['Price_trener']=>
string(4) "5.00"
}
[45]=>array(2){
['Price_customer']=>
string(5) "60.00",
['Price_trener']=>
string(5) "10.00"
}
  }
}

Надеюсь вопрос ясен.. Спасибо за ваше время

var trener_services;

$('body').on('change', '.service_check', function() {
 trener_services = new Array();     
    $('.service_check:checked').each(function(){
    var sid = $(this).val();
    var trener_id = $(this).attr('data-trener');

    if (!trener_services[trener_id]){
    trener_services[trener_id] = [];
    }
  trener_services[trener_id].push($(this).val());
  console.info(trener_services);
})
})
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<table class = "table table-hover table-striped text-left trener_service_table tren_ser_13">
<thead>
<tr>
<th class = "text-left success">Select</th>
<th class = "text-left success mw20">Service type</th>
<th class = "text-left success">Price customer</th>
<th class = "text-left success">Price trener</th>
</tr>
</thead>
<tbody><tr class = "tren_ser_row_47"> 
<td><input id = "service_check_47" data-trener = "13" type = "checkbox" class = "service_check" value = "47"></td>
<td><label for = "service_check_47">Single play</label></td>
<td><input data-id = "47" id = "trener_client_price_47" class = "short client_price client_price_47" type = "text" value = "10.00"></td>
<td><input data-id = "47" id = "trener_bonus_price_47" class = "short bonus_price_47" type = "text" value = "5.00"></td>
</tr>
<tr class = "tren_ser_row_45">    
<td><input id = "service_check_45" data-trener = "13" type = "checkbox" class = "service_check" value = "45"></td>
<td><label for = "service_check_45">Double play</label></td>
<td><input data-id = "45" id = "trener_client_price_45" class = "short client_price client_price_45" type = "text" value = "60.00"></td>
<td><input data-id = "45" id = "trener_bonus_price_45" class = "short bonus_price_45" type = "text" value = "10.00"></td>
</tr>
<tr class = "tren_ser_row_46">    
<td><input id = "service_check_46" data-trener = "13" type = "checkbox" class = "service_check" value = "46"></td>
<td><label for = "service_check_46">Triple play</label></td>
<td><input data-id = "46" id = "trener_client_price_46" class = "short client_price client_price_46" type = "text" value = "50.00"></td>
<td><input data-id = "46" id = "trener_bonus_price_46" class = "short bonus_price_46" type = "text" value = "10.00"></td>
</tr>
</tbody>
</table>

У вас есть var trener_services = ... внутри вашего обработчика событий. Это совершенно не связано с глобальным var trener_services = ..., который вы определяете вне обработчика событий. То есть все, что вы делаете с trener_services внутри вашего обработчика событий, вообще не влияет на глобальную переменную...

derpirscher 15.02.2023 10:54

Если вы создаете массив с числовым индексом, пробелы будут автоматически заполнены пустыми значениями; вместо этого вы можете использовать объект для цифровых клавиш . Затем вы можете использовать Object.keys(...), Object.values(...) и Object.entries(...) для извлечения содержимого, как показано здесь

SaschaM78 15.02.2023 10:57

@derpirscher, это была ошибка копирования/вставки

Europeuser 15.02.2023 11:05

Вы сделали еще хуже... Теперь у вас вообще нет глобальной переменной, поэтому вы каждый раз просто отбрасываете результат выполнения своей функции...

Michael G 15.02.2023 11:10

Самым простым решением было бы иметь глобальный var trener_services; вне вашего обработчика событий, а затем trener_services = new Array(); (то есть без var) внутри вашего обработчика событий. Таким образом, вы пересоздаете весь массив каждый раз, когда меняется статус проверки. Или посмотрите ответ @MichaelG, в котором используется объект вместо разреженного массива.

derpirscher 15.02.2023 11:30

@derpirscher Я изменил код, как было предложено, но по-прежнему печатает много неопределенностей в массиве, который очень хорошо объяснил SaschaM78.

Europeuser 15.02.2023 11:36

Да, это природа разреженного массива. Вы заполняете только определенные индексы, все остальные не определены... Использование объекта определенно лучший способ

derpirscher 15.02.2023 11:51
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему &apos;[] instanceof Object&apos; возвращает &quot;true&quot;?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
0
7
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как предложил один комментатор, вы должны использовать Объект вместо Массив. (Ваш trener_id — это строка, а не число, если только JQuery автоматически не преобразует строки в числа; я не использую JQuery, поэтому не знаю.)

//this is a global variable so you can use it elsewhere
let trener_services;

document.body.addEventListener( "change", () => {

    trener_services = Object.fromEntries(
        //get all the checked services:
        [ ...document.querySelectorAll('.service_check:checked') ].
            //map them to object entries of the form [ key, value ]
            map( checkboxElement => [

                //key: the data-trener attribute
                //checkboxElement.getAttribute( "data-trener" ),

                //key: the checkbox's value field
                checkboxElement.value,

                //value: an array of the checkbox's value as well as the two sibling values you wanted
                [
                    checkboxElement.value,
                    document.querySelector( "#trener_client_price_" + checkboxElement.value ).value,
                    document.querySelector( "#trener_bonus_price_" + checkboxElement.value ).value
                ]

            ] )
    );

    console.info( trener_services );

})

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

//this is a global variable so you can use it elsewhere
let trener_services;

document.body.addEventListener( "change", () => {

    trener_services = Object.fromEntries(
        //get all the checked services:
        [ ...document.querySelectorAll('.service_check:checked') ].
            //map them to object entries of the form [ key, value ]
            map( checkboxElement => [

                //key: the data-trener attribute
                //checkboxElement.getAttribute( "data-trener" ),

                //key: the checkbox's value field
                checkboxElement.value,

                //value: only the checkbox's value
                checkboxElement.value

            ] )
    );

    console.info( trener_services );

})

Я создал jsfiddle: jsfiddle.net/w5qor2pn и обнаружил, что ваш код печатает каждую службу в отдельном массиве, а не все 3, например, в 1 массиве. Я прав?

Europeuser 15.02.2023 11:32

Как вы спросили, «возможно ли и как добавить подмассив, в котором к каждому выбранному значению услуги привязаны цена клиента и цена тренера». Я добавлю вторую копию, которая этого не делает, я полагаю?

Michael G 15.02.2023 11:34

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

Europeuser 15.02.2023 11:41

Я отредактировал свой вопрос и добавил php-эквивалент желаемого формата массива с выбранными сервисами trener # 13, но одновременно будет выбрано более 1 trener.

Europeuser 15.02.2023 11:53

Майкл Г.: После того, как я провел несколько тестов, ваш первый код может выполнять нужную мне работу, и поэтому я принял ваш ответ как правильный! Большое спасибо за ваше время всем вам, ребята!

Europeuser 15.02.2023 12:04

Вы пытаетесь использовать эту информацию в PHP? К сожалению, я не думаю, что у меня достаточно опыта работы с PHP, чтобы помочь (я никогда не использовал массивы PHP). Я даже не знаю, как вы отправляете это на свой сервер... но какой бы формат вы ни использовали, вам придется каким-то образом извлечь и преобразовать его на другом конце, используя функцию, написанную на PHP. Извините, может кто ответит.

Michael G 15.02.2023 12:05

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

Europeuser 15.02.2023 17:08

@Europeuser, поскольку вы решили использовать «data-trener» в качестве своего ключа, и он одинаков для всех служб (13), они перезаписывают друг друга. (Как и в массиве, только 1 данные могут быть в слоте 13. Добавьте данные в слот 13 снова, и вы перезапишете/сотрете все, что было раньше). Вам нужно будет использовать уникальный ключ, а не «дата-тренер». Глядя на ваш массив PHP, я думаю, вы хотели использовать значение флажка? (Возможно?) Я обновлю код, но если вы не уверены, чего хотите... Возможно, вы этого не получите.

Michael G 16.02.2023 11:47

Другие вопросы по теме