Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как перенести элемент из одного места в другое?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Куда и что надо перенести:

    const where = '.container';
    const what = '.wrapper-item h3';

    Конечно, можете и дальше использовать jquery:

    $(where).prepend(function() {
      return $(what, this);
    });

    Но это совсем не обязательно:

    document.querySelectorAll(where).forEach(n => {
      const el = n.querySelector(what);
    
      n.prepend(el);
      // или
      n.insertBefore(el, n.firstChild);
      // или
      n.insertAdjacentElement('afterbegin', el);
      // или
      n.firstChild.replaceWith(el, n.firstChild);
      // или
      n.replaceChildren(el, ...n.childNodes);
    });
    Ответ написан
    1 комментарий
  • Как задать 2 элементу класс active?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Кому и какой надо добавить класс:

    const index = 1;
    const className = 'active';

    Добавляем:

    navigation.children[index]?.classList.add(className);

    Это если не трогать уже написанный код. Но вообще, можно и переписать создание элементов, добавив проверку текущего индекса. Какие тут есть варианты:

    navigation.innerHTML = objectNavigation
      .map((n, i) => `
        <div class="${i === index ? className : ''}">
          <img src="${n.image}">
        </div>`)
      .join('');

    или

    navigation.append(...objectNavigation.map((n, i) => {
      const div = document.createElement('div');
      const img = document.createElement('img');
      img.src = n.image;
      div.append(img);
      div.classList.toggle(className, i === index);
      return div;
    }));

    или

    for (const [ i, n ] of objectNavigation.entries()) {
      navigation.appendChild(document.createElement('div'));
      navigation.lastChild.appendChild(new Image);
      navigation.lastChild.lastChild.src = n.image;
      navigation.lastChild.className = i === index ? className : '';
    }
    Ответ написан
    Комментировать
  • Каким образом можно создать объект, используя имя класса, записанное в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сложите классы в объект.
    const classes = {
      Class1: class {
        constructor(val) {
          this.val = val;
        }
    
        method1() {
          console.log('Class1', this.val);
        }
      },
      Class2: class {
        constructor(val1, val2) {
          this.val1 = val1;
          this.val2 = val2;
        }
    
        method2() {
          console.log('Class2', this.val1, this.val2);
        }
      },
    };
    
    function createInstanceAddCallMethod(className, constructorParams, methodName) {
      const instance = new classes[className](...constructorParams);
      instance[methodName]();
    }
    
    createInstanceAddCallMethod('Class1', [ 69 ], 'method1');
    createInstanceAddCallMethod('Class2', [ 187, 666 ], 'method2');
    Ответ написан
    Комментировать
  • Почему неправильно считается сумма двух минимальных элементов массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const newArray = numbers.filter(i => i !== firstMin);

    Что, если минимальный элемент представлен в нескольких экземплярах? Вы их все выкинете.

    Можно найти индекс минимального элемента и фильтровать по индексу:

    function sumTwoSmallestNumbers(nums) {  
      const iMin = nums.indexOf(Math.min(...nums));
      return nums[iMin] + Math.min(...nums.filter((_, i) => i !== iMin));
    }

    Это если идти вашим путём. Но есть и иные способы решить задачу. Например, можно отсортировать массив и взять два крайних элемента:

    const sumTwoSmallestNumbers = ([...nums]) => nums
      .sort((a, b) => b - a)
      .slice(-2)
      .reduce((acc, n) => acc + n, 0);

    Или, сосчитать, кто сколько раз повторяется и выбирать второе слагаемое в зависимости от количества повторений первого:

    function sumTwoSmallestNumbers(nums) {
      const count = Object.entries(nums.reduce((acc, n) => (acc[n] = -~acc[n], acc), {}));
      return +count[0][0] + +count[+(count[0][1] === 1)][0];
    }

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

    function sumTwoSmallestNumbers(nums) {
      let min1 = Infinity;
      let min2 = Infinity;
    
      for (const n of nums) {
        if (n < min1) {
          [ min1, min2 ] = [ n, min1 ];
        } else if (n < min2) {
          min2 = n;
        }
      }
    
      return min1 + min2;
    }
    
    // или
    
    const sumTwoSmallestNumbers = nums =>
      eval(nums.reduce(([ min1, min2 ], n) => 
        n < min1 ? [    n, min1 ] :
        n < min2 ? [ min1,    n ] :
                   [ min1, min2 ]
      , [ Infinity, Infinity ]).join('+'));
    Ответ написан
  • Возможно ли обработать Promise.all без второго Promise.all?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Promise
      .all(urls.map(url => fetch(url).then(result => result.json())))
      .then(results => results.forEach(result => console.log(result.id)));
    Ответ написан
    Комментировать
  • Как перемножить два массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как перемножить элементы массива:

    const mul = arr =>
      arr.reduce((acc, n) => acc * n, 1);
    
    // или
    
    const mul = arr =>
      eval(arr.join('*')) ?? 1;
    
    // или
    
    function mul(arr) {
      let result = 1;
      for (const n of arr) {
        result *= n;
      }
      return result;
    }
    
    // или
    
    function mul(arr) {
      let result = 1;
      for (let i = 0; i < arr.length; i++) {
        result = result * arr[i];
      }
      return result;
    }
    
    // или
    
    const mul = (arr, i = 0) =>
      i < arr.length
        ? arr[i] * mul(arr, -~i)
        : 1;

    Бежим по массиву с количествами элементов, получаем из массива с данными подмассивы указанной длины, перемножаем их содержимое:

    const result = count.map(function(n) {
      return mul(data.slice(this[0], this[0] += n));
    }, [ 0 ]);

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

    const result = count.map(n => mul(data.splice(0, n)));
    Ответ написан
    1 комментарий
  • Слияние объектов не работает в "codewars", можете объяснить пожалуйста?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function combine(a = {}, b = {}, c = {}) {

    Читаю текст задачи сверху вниз, снизу вверх, так, сяк, наперекосяк, и никак не могу найти там место, где говорится, что объектов в функцию будет передаваться не больше трёх.

    Как обработать заранее неизвестное количество аргументов?

    Можно собрать их в массив:

    const combine = (...arr) => arr
      .flatMap(Object.entries)
      .reduce((acc, [ k, v ]) => (acc[k] = (acc[k] ?? 0) + v, acc), {});

    Или, воспользоваться уже готовым массивоподобным объектом:

    function combine() {
      const result = {};
    
      for (const n of arguments) {
        for (const k in n) {
          if (n.hasOwnProperty(k)) {
            if (!result.hasOwnProperty(k)) {
              result[k] = 0;
            }
    
            result[k] += n[k];
          }
        }
      }
    
      return result;
    }
    Ответ написан
    1 комментарий
  • Как найти самое часто встречаемое число в массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const mostFrequentNum = Array
      .from(arr.reduce((acc, n) => acc.set(n, -~acc.get(n)), new Map))
      .reduce((max, n) => max[1] > n[1] ? max : n, [ , 0 ])
      .at(0);

    или

    const mostFrequentNum = Object
      .entries(arr.reduce((acc, n) => (acc[n] = (acc[n] ?? 0) + 1, acc), {}))
      .reduce((acc, n) => (acc[n[1]] = +n[0], acc), [])
      .pop();
    Ответ написан
    2 комментария
  • Вложенной деструктуризации массива не существует?

    0xD34F
    @0xD34F Куратор тега JavaScript
    let [0: [fruit1, fruit2, fruit3]] = arr; //Uncaught SyntaxError: Invalid destructuring assignment target

    Скажите, а когда массив создаёте, вы тоже индексы явно прописываете? Ну вот и тут не надо.
    А если надо пропустить какие-то индексы - просто добавьте запятых:

    const arr = [
      [ 1, 2, 3 ],
      [ 5, 6, 7 ],
      [ 7, 8, 9 ],
    ];
    
    const [ , [ , val1 ], [ ,, val2 ] ] = arr;
    
    console.log(val1, val2); // 6 9

    Или можно заменить квадратные скобки фигурными - массив это тоже объект.
    Так что и деструктурировать его как обычный объект не возбраняется:

    const arr = [
      [ 1, 2, 3 ],
      [ 5, 6, 7 ],
      [ 7, 8, 9 ],
    ];
    
    const { 1: { 1: val1 }, 2: { 2: val2 } } = arr;
    
    console.log(val1, val2); // 6 9
    Ответ написан
    Комментировать
  • Как у объекта в sessionStorage получить проверку количества ключей?

    0xD34F
    @0xD34F Куратор тега JavaScript
    раз:

    The keys and the values are always in the UTF-16 string format...

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Object.values(t).forEach(n => {
      n.children?.sort((a, b) => (a.order - b.order) || a.name.localeCompare(b.name));
    });
    Ответ написан
    2 комментария
  • Как перемножить числа в том же массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как получить квадрат числа:

    const square = n => n ** 2;
    
    // или
    
    const square = n => n * n;
    
    // или
    
    const square = n => Math.pow(n, 2);

    Как обновить массив:

    arr.forEach((n, i, a) => a[i] = square(n));
    
    // или
    
    arr.splice(0, arr.length, ...arr.map(square));
    
    // или
    
    for (const [ i, n ] of arr.entries()) {
      arr[i] = square(n);
    }
    
    // или
    
    for (let i = 0; i < arr.length; i++) {
      arr[i] = square(arr[i]);
    }
    Ответ написан
    3 комментария
  • Почему выводится ошибка Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'push')?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Так написано же всё в сообщении об ошибке. Кинуть в консоль получаемые данные догадались, а произвести аналогичную операцию над table.data и увидеть, что оно undefined - уже нет?

    Как мне изменить код, чтобы исправить ошибку?

    Код настолько отвратительный, что я бы переписал с нуля:

    const countries = Array.from({ length: 3 }, prompt);
    
    new gridjs.Grid({
      columns: [
        'Code',
        { name: 'Flag', formatter: val => gridjs.html(`<img src="${val}">`) },
        'Name',
        'Capital',
        'Population',
      ],
      data: () => Promise.all(countries.map(n =>
        fetch(`//restcountries.com/v3.1/name/${n}`)
          .then(r => r.json())
          .then(([ r ]) => [
            r.altSpellings[0],
            r.flags.png,
            r.name.common,
            r.capital[0],
            r.population,
          ])
          .catch(() => [ ,,`${n} - это не страна`,, ])
      )),
    }).render(document.querySelector('#wrapper'));
    Ответ написан
  • Как выдернуть массив чисел из строки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    (str.match(/[0-9]+/g) ?? []).map(Number)
    
    // или
    
    Array.from(str.matchAll(/\d+/g), n => +n)
    
    // или
    
    str.split(/\D+/).filter(Boolean).map(parseFloat)
    
    // или
    
    eval(`[${str.replace(/\D+/g, (m, i) => i ? ',' : '')}]`)
    
    // или
    
    [...str].reduce((acc, n, i, a) => (
      isNaN(n) || (isNaN(a[i - 1]) && acc.push(0), acc.push(acc.pop() * 10 + n * 1)),
      acc
    ), [])
    Ответ написан
    Комментировать
  • Преобразование объекта в примитив, почему прилетает object Object?

    0xD34F
    @0xD34F Куратор тега JavaScript
    ищет метод toString - его нет

    То есть, если попробовать получить test.toString, то результатом будет undefined. Вы проверьте, так ли это. Будете удивлены.
    Ответ написан
  • Как получить значение ячейки th и присвоить это значение в data-attr td?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Какие таблицы будем обрабатывать:

    const tables = document.querySelectorAll('селектор таблиц');

    Собираем в массив заголовки столбцов, используем элементы этого массива для задания значений атрибута. Как определять, какое именно значение брать для конкретной ячейки? - очевидно же, у них одинаковые индексы:

    for (const { tHead, tBodies } of tables) {
      const labels = Array.prototype.map.call(
        tHead.rows[0].cells,
        th => th.textContent
      );
    
      for (const { rows } of tBodies) {
        for (const { cells } of rows) {
          for (const [ i, label ] of labels.entries()) {
            cells[i].dataset.label = label;
          }
        }
      }
    }

    или

    tables.forEach(table => {
      table.querySelectorAll('tbody td').forEach(function(td) {
        td.setAttribute('data-label', this[td.cellIndex]);
      }, Array.from(table.querySelectorAll('thead th'), th => th.innerText));
    });
    Ответ написан
    Комментировать
  • Как убрать объекты дубликаты из массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вот функция уникализации по нескольким параметрам:

    const unique = function*(data, keys = n => n) {
      const picked = new Map;
    
      for (const n of data) {
        const p = []
          .concat(keys(n))
          .reduce((acc, k) => acc.set(k, acc.get(k) ?? new Map).get(k), picked);
    
        if (!p.set(this, p.has(this)).get(this)) {
          yield n;
        }
      }
    }.bind(Symbol());

    А вот так её можно применять в вашем случае:

    // собираем новый массив
    const newArr = Array.from(unique(arr, n => [ n.name, n.value ]));
    
    // обновляем существующий
    arr.splice(0, arr.length, ...unique(arr, Object.values));
    Ответ написан
    1 комментарий
  • Как собрать массив из двух других массивов по совпадению id?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = data
      .flatMap(n => n.values)
      .filter(n => n.Ids.some(m => arr.includes(m)))
      .map(({ id, title }) => ({ id, title }));

    или

    const inArr = Set.prototype.has.bind(new Set(arr));
    const data.reduce((acc, { values }) => (
      values.forEach(({ Ids, ...n }) => Ids.some(inArr) && acc.push(n)),
      acc
    ), []);
    Ответ написан
    1 комментарий
  • Как из двух массивов получить те объекты, которые есть в одном и отсутствуют в другом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Делаем просто, ровно то, что спрошено в вопросе:

    const result = allCass.filter(function(n) {
      return !this.has(n.id);
    }, new Set(defaultCass.map(n => n.id)));

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

    function* diff(data1, data2, key = n => n) {
      const getKey = key instanceof Function ? key : n => n[key];
      const keys = new Set;
    
      for (const n of data2) {
        keys.add(getKey(n));
      }
    
      for (const n of data1) {
        if (!keys.has(getKey(n))) {
          yield n;
        }
      }
    }

    В вашем случае применять так:

    const result = [...diff(allCass, defaultCass, 'id')];

    А можно и так:

    Array.from(diff('abcdE', 'AcD', n => n.toLowerCase())) // ['b', 'E']

    Или так:

    for (const n of diff(Array(8).keys(), Array(5).keys())) {
      console.log(n); // 5 6 7
    }
    Ответ написан
    6 комментариев
  • Как сформировать новый массив объектов, сделав слияние по некоторому параметру?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Пытался сделать через reduce из библиотеки lodash

    Давайте так - или lodash, или reduce, но не оба сразу:

    const newArr = _.map(_.groupBy(arr, 'merch'), (v, k) => ({
      merch: +k,
      games: _.uniq(_.flatMap(v, 'games')),
    }));

    const newArr = Object
      .entries(arr.reduce((acc, n) => ((acc[n.merch] ??= []).push(...n.games), acc), {}))
      .map(n => ({ merch: +n[0], games: [...new Set(n[1])] }));
    Ответ написан
    Комментировать