Собрать объект, пройдя по элементам

251
17 июля 2021, 20:00

Есть группа элементов, выглядят они так:

<div>
    <input type="text" name="nameOne_aaa">
    <input type="text" name="nameOne_bbb">
    <input type="text" name="nameOne_ccc">
    <input type="text" name="nameOne_ddd">
</div>
<div>
    <input type="text" name="nameTwo_aaa">
    <input type="text" name="nameTwo_bbb">
    <input type="text" name="nameTwo_ccc">
    <input type="text" name="nameTwo_ddd">
</div>

Как из этого собрать объект, такого типа:

{
    "nameOne": {
        "aaa": "",
        "bbb": "",
        "ccc": "",
        "ddd": ""
    },
    "nameTwo": {
        "aaa": "",
        "bbb": "",
        "ccc": "",
        "ddd": ""
    }
}

Где arr[n] - ключ равен значению из атрибута name (части до _), значение (arr[n][n]), равно другому объекту,
где arr[n][n] - ключ равен атрибуту [name] (части после _), а значение равно value этого input'а или textarea

Answer 1

let input = document.querySelectorAll('input[type="text"]'); 
 
let json = {} 
 
for( let i = 0; i < input.length; i++ ){ 
  let name = input[i].name.match(/^(.+?)_(.+)$/); // (*1) 
  let key = name[1]; 
  let val = name[2]; 
 
  if( !json[key] ){ // Если объекта с найденным именем еще нет - создаем. 
    json[key] = {} 
  } 
 
  json[key][val] = ""; 
} 
 
console.log( json );
<div> 
  <input type="text" name="nameOne_aaa"> 
  <input type="text" name="nameOne_bbb"> 
  <input type="text" name="nameOne_ccc"> 
  <input type="text" name="nameOne_ddd"> 
</div> 
 
<div> 
  <input type="text" name="nameTwo_aaa"> 
  <input type="text" name="nameTwo_bbb"> 
  <input type="text" name="nameTwo_ccc"> 
  <input type="text" name="nameTwo_ddd"> 
</div>

(*1): .name.match(/^(.+?)_(.+)$/)^ начало строки, $ - конец сроки. . точка совпадает с любым символом, а + плюсик означает "один или много раз". При этом, match возвращает массив из найденных совпадений.
Скажем, их строки nameTwo_aaa вернет ["nameTwo_aaa", "nameTwo", "aaa"] — оттуда и можно достать 2-й и 3-й элементы по индексам [1] и [2]

P.s. да, разумнее было использовать split, как в соседнем ответе!)

Answer 2

let inputs = document.querySelectorAll('input'); 
 
const obj = {}; 
 
inputs.forEach( input => { 
   
  const names = input.getAttribute("name").split('_'); 
  
  if (!obj.hasOwnProperty(names[0])) { 
    obj[names[0]] = {}; 
  } 
   
  obj[names[0]][names[1]] = ''; 
   
}); 
 
console.log(obj);
<div class="select"> 
    <input type="text" name="nameOne_aaa"> 
    <input type="text" name="nameOne_bbb"> 
    <input type="text" name="nameOne_ccc"> 
    <input type="text" name="nameOne_ddd"> 
</div> 
 
<div class="select"> 
    <input type="text" name="nameTwo_aaa"> 
    <input type="text" name="nameTwo_bbb"> 
    <input type="text" name="nameTwo_ccc"> 
    <input type="text" name="nameTwo_ddd"> 
</div>

Answer 3

Вот так, например:

let result = [...document.querySelectorAll('input')] 
  .map(el => el.name) 
  .reduce((a, e) => { 
    let b = e.split('_'), c = b[0]; 
    return (a[c] || (a[c] = {}))[b[1]] = "", a; 
  }, {}); 
 
console.log(result)
<div> 
    <input type="text" name="nameOne_aaa"> 
    <input type="text" name="nameOne_bbb"> 
    <input type="text" name="nameOne_ccc"> 
    <input type="text" name="nameOne_ddd"> 
</div> 
 
<div> 
    <input type="text" name="nameTwo_aaa"> 
    <input type="text" name="nameTwo_bbb"> 
    <input type="text" name="nameTwo_ccc"> 
    <input type="text" name="nameTwo_ddd"> 
</div>

READ ALSO
Slider for Bootstrap (ползунок для цен)

Slider for Bootstrap (ползунок для цен)

В интернет-магазине использую библиотеку Slider for Bootstrap, для вывода ползунка выбора диапазона цены

259
Как использовать в конструкторе метод в методе с таймаутом?

Как использовать в конструкторе метод в методе с таймаутом?

Вызываю метод sayMeow() в методе voice() без таймаутаВсе норм

201