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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Где элементы находятся, какой класс надо добавить и начиная с какого по счёту элемента:

    const parent = document.querySelector('.container');
    const className = 'green';
    const startFrom = 4;

    Добавляем:

    parent
      .querySelectorAll(`:scope > :nth-child(n + ${startFrom + 1})`)
      .forEach(n => n.classList.add(className));
    
    // или
    
    for (const n of Array.prototype.slice.call(parent.children, startFrom)) {
      n.classList.add(className);
    }
    
    // или
    
    for (let el = parent.children[startFrom]; el; el = el.nextElementSibling) {
      el.classList.add(className);
    }
    
    // или, также удаляем класс (если вдруг есть) у тех, кому он не должен быть добавлен
    
    for (let i = 0; i < parent.children.length; i++) {
      parent.children[i].classList.toggle(className, i >= startFrom);
    }
    Ответ написан
    1 комментарий
  • Как сгенерировать массив только из уникальных чисел определенной длины?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Какие есть способы создания массива:

    • Создавать случайные числа, пока не наберётся сколько надо.
    • Создать массив, состоящий из всех чисел интервала, выдернуть из него сколько надо случайных.
    • Создать массив, состоящий из всех чисел интервала, перемешать его, взять кусок нужного размера.

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

    • Кидать ошибку.
    • Создавать массив с длиной меньше указанной.

    Вот как-то так:

    function createRandomArr(size, min, max) {
      if (size > (max -= ~-min)) {
        throw 'невозможно создать массив указанного размера';
      }
    
      const values = new Set;
      for (; values.size < size; values.add(min + Math.random() * max | 0)) ;
      return [...values];
    }

    или

    function createRandomArr(size, min, max) {
      const len = max - min + 1;
      const arr = [...Array(len).keys()];
    
      return Array.from(
        { length: Math.min(size, len) },
        () => min + arr.splice(Math.random() * arr.length | 0, 1)[0]
      );
    }

    или

    function createRandomArr(size, min, max) {
      const arr = Array.from(
        { length: max - min + 1 },
        (_, i) => i + min
      );
    
      for (let i = arr.length; --i > 0;) {
        const j = Math.floor(Math.random() * (i + 1));
        [ arr[j], arr[i] ] = [ arr[i], arr[j] ];
      }
    
      return arr.slice(-size);
    }
    Ответ написан
    Комментировать
  • Как можно сократить запись создания одинаковых элементов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Значения собрать в массив: const values = [ id, sum, system, date ];.

    Дальше есть варианты:

    payment.innerHTML = values.map(n => `<td>${n}</td>`).join('');
    
    // или
    
    values.forEach(n => payment.insertCell().textContent = n);
    
    // или
    
    payment.append(...values.map(n => {
      const td = document.createElement('td');
      td.innerText = n;
      return td;
    }));

    Или, то же самое, но с массивом ключей вместо значений:

    - function createPayment({id, sum, system, date}) {
    + function createPayment(data) {

    - const values = [ id, sum, system, date ];
    + const keys = [ 'id', 'sum', 'system', 'date' ];

    - values.forEach(n => payment.insertCell().textContent = n);
    + keys.forEach(n => payment.insertCell().textContent = data[n]);
    Ответ написан
    Комментировать
  • Как рекурсивно обойти древовидный объект?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const getKeys = obj =>
      obj instanceof Object
        ? Object.entries(obj).flatMap(n => [ n[0], ...getKeys(n[1]) ])
        : [];
    
    const keys = getKeys(obj);

    или

    function* getKeys(obj) {
      if (Object(obj) === obj) {
        for (const k in obj) if (obj.hasOwnProperty(k)) {
          yield k;
          yield* getKeys(obj[k]);
        }
      }
    }
    
    const keys = [...getKeys(obj)];
    Ответ написан
    Комментировать
  • Как оставить в объекте три самых больших числа?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сколько свойств должно быть в объекте: const propsCount = 3;.

    Собираем новый объект:

    const newObj = Object.fromEntries(Object
      .entries(obj)
      .sort((a, b) => a[1] - b[1])
      .slice(-propsCount)
    );

    Удаляем свойства существующего:

    Object
      .entries(obj)
      .sort((a, b) => b[1] - a[1])
      .slice(propsCount)
      .forEach(n => delete obj[n[0]]);
    Ответ написан
    3 комментария
  • Как вырезать текст с определенного символа и до конца цифр?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const numbers = (str.match(/>\d+/g) ?? []).map(n => +n.slice(1));
    
    // или
    
    const numbers = Array.from(str.matchAll(/(?<=>)\d+/g), Number);
    
    // или
    
    const numbers = (function get(reg) {
      const m = reg.exec(str)?.[1];
      return m ? [ parseInt(m), ...get(reg) ] : [];
    })(/>(\d+)/g);
    Ответ написан
    1 комментарий
  • Как удвоить каждый символ в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    ''.concat(...Array.from(str, n => n.repeat(2)))
    // или
    str.replace(/./g, '$&$&')
    // или
    str.replace(/./g, m => Array(3).join(m))
    // или
    str.replace(/(?=.)/g, (m, i) => str[i])
    // или
    [...str].flatMap(n => Array(2).fill(n)).join('')
    // или
    [].map.call(str, n => `${n}${n}`).join``
    // или
    str.split('').reduce((acc, n) => acc + n + n, '')
    Ответ написан
    Комментировать
  • Как сложить и узнать среднее значение объекта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сложить объекты в массив, и

    const averageAge = arr.reduce((acc, n) => acc + n.age, 0) / arr.length;

    Это если делать просто и ровно то, что спрошено. Но можно решить задачу и в более общем виде - сделаем функцию, вычисляющую среднее передаваемого ей итерируемого объекта:

    function avg(data, key = n => n) {
      const getVal = key instanceof Function ? key : n => n[key];
      let sum = 0;
      let count = 0;
    
      for (const n of data) {
        sum += getVal(n);
        count += 1;
      }
    
      return sum / count;
    }

    В вашем случае применять так: const averageAge = avg(arr, 'age');.

    Другие варианты использования:

    avg(Array(10).keys()) // 4.5
    avg('12345', Number) // 3
    avg(document.images, n => n.width) // сами посмотрите, сколько тут получится
    Ответ написан
    Комментировать
  • Как разбить массив на массивы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    arr.reduce((acc, n, i) => (
      (!i || n === 1) && acc.push([]),
      acc[acc.length - 1].push(n),
      acc
    ), [])
    Ответ написан
    2 комментария
  • Как найти и сделать первую букву заглавной самого короткого слова в массиве?

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

    const index = arr.reduce((min, n, i, a) => a[min]?.length <= n.length ? min : i, -1);
    if (index !== -1) {
      arr[index] = arr[index][0].toUpperCase() + arr[index].slice(1);
    }

    Если слов с минимальной длиной может быть несколько и надо изменить все:

    const [ indexes ] = arr.reduce((min, n, i) => (
      n.length < min[1] && (min = [ [], n.length ]),
      n.length === min[1] && min[0].push(i),
      min
    ), [ [], Infinity ]);
    
    indexes.forEach(n => arr[n] = arr[n].replace(/./, m => m.toUpperCase()));
    Ответ написан
    Комментировать
  • Как распарсить время для понимания JS?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const date = new Date(str.replace(/\S+/, m => m.split('.').reverse().join('-')));

    или

    const date = new Date(str.replace(/(\d+)\.(\d+)\.(\d+)/, '$3-$2-$1'));

    или

    const [ day, month, year, hours, minutes, seconds ] = str.split(/\D/);
    const date = new Date(year, month - 1, day, hours, minutes, seconds);

    или (day.js):

    const date = dayjs(str, 'DD.MM.YYYY HH:mm:ss').toDate();
    Ответ написан
    Комментировать
  • Как правильно отсортировать массив объектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function sort([...arr]) {
      const max = arr.reduce((max, n) => max?.population > n.population ? max : n, null);
      return arr.sort((a, b) => a === max ? -1 : b === max ? 1 : a.city.localeCompare(b.city));
    }
    Ответ написан
    1 комментарий
  • Как перебрать все элементы с одним классом, выбрать у них тексты и добавить в одну переменную через запятую?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каком классе идёт речь: const className = 'model';

    Как получить элементы:

    const elements = document.querySelectorAll(`.${className}`);
    // или
    const elements = document.getElementsByClassName(className);

    Как извлечь из элемента его текст:

    const getText = el => el.textContent;
    // или
    const getText = el => el.innerText;
    // или
    const getText = el => el.innerHTML;
    // или
    const getText = el => el.lastChild.nodeValue;
    // или
    const getText = el => el.childNodes[0].data;

    Перебираем элементы, достаём тексты, склеиваем:

    const result = Array.from(elements, getText).join(', ');
    
    // или
    
    const result = ''.concat(...[...elements].flatMap((n, i) => (
      n = getText(n),
      i ? [ ', ', n ] : n
    )));
    
    // или
    
    const result = Array.prototype.reduce.call(
      elements,
      (acc, n, i) => acc + (i ? ', ' : '') + getText(n),
      ''
    );
    
    // или
    
    const result = (function get(i, n = elements[i]) {
      return n
        ? `${i ? ', ' : ''}${getText(n)}${get(i + 1)}`
        : ''
    })(0);
    Ответ написан
    1 комментарий
  • Как сократить код, заменив for на reduce?

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

    const { x: countX = 0, o: countO = 0 } = Array
      .from(str.toLowerCase())
      .reduce((acc, n) => (acc[n] = (acc[n] ?? 0) + 1, acc), {});

    А вот ещё короче без reduce'а:

    const [ countX, countO ] = [ /x/i, /o/i ].map(n => ~-str.split(n).length);
    Ответ написан
    5 комментариев
  • Как остановить рекурсию возврата функции?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Нет аргументов - нет рекурсивного вызова:

    const xxx = (() => {
      function f() {
        return arguments.length ? f.bind([].concat.apply(this, arguments)) : this;
      }
    
      return f.bind([]);
    })();
    
    // или
    
    const xxx = (...args1) => (...args2) =>
      args2.length
        ? xxx(...args1, ...args2)
        : args1;

    xxx(1, 2)(3, 4)() // [1, 2, 3, 4]
    
    const t = xxx(1, 3, 5);
    t(7)() // [1, 3, 5, 7]
    t(3)(1)() // [1, 3, 5, 3, 1]
    Ответ написан
    Комментировать
  • Как в массиве с массивами найти объект у которого значение больше чем у других объектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    В заголовке вопроса:

    найти объект

    В тексте:

    найти самое большое значение

    Ну и как это понимать? Сами-то в курсе, чего вам надо?

    Первое:

    const obj = arr.flat().reduce((max, n) => max?.age > n.age ? max : n, null);

    Второе:

    const val = Math.max(...arr.flat().map(n => n.age));

    Кстати, а что если максимум представлен в нескольких экземплярах? Можно получить все такие объекты:

    const objs = arr.reduce((acc, n) => (
      n.forEach(m => (
        m.age > acc[0] && (acc = [ m.age, [] ]),
        m.age === acc[0] && acc[1].push(m)
      )),
      acc
    ), [ -Infinity, [] ])[1];
    Ответ написан
    Комментировать
  • Как уникализировать массив объектов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Собираем ключ-значение, выдёргиваем значения:

    [...new Map(arr.map(n => [ n.value, n ])).values()]
    
    // или
    
    Object.values(arr.reduce((acc, n) => (acc[n.value] ??= n, acc), {}))

    Фильтрация, запоминаем кого встретили, первый раз пропускаем, остальные нет:

    arr.filter(function(n) {
      return !(this[n.value] = this.hasOwnProperty(n.value));
    }.bind({}))
    
    // или
    
    arr.filter(function({ value }) {
      return !this.set(value, this.has(value)).get(value);
    }, new Map)
    
    // или
    
    arr.filter(((picked, { value: n }) =>
      !picked.has(n) && picked.add(n)
    ).bind(null, new Set))

    Фильтрация, ищем элемент похожий на текущий, его же и нашли - окей (на самом деле не всегда, если в массиве присутствует ссылка на один объект несколько раз, и сравниваем именно ссылки, а не индексы, то такие дубликаты не будут обнаружены):

    arr.filter((n, i, a) => n === a.find(m => Object.is(m.value, n.value)))
    
    // или
    
    arr.filter((n, i, a) => i === a.findIndex(m => m.value === n.value))

    Ну и чего-нибудь странного ещё добавим:

    Array.from(
      new Set(arr.map(n => n.value)),
      n => arr.find(m => m.value === n)
    )
    
    // или
    
    arr
      .slice()
      .sort((a, b) => a.value.localeCompare(b.value))
      .filter((n, i, a) => n.value !== a[i - 1]?.value)
    Ответ написан
    1 комментарий
  • Как очистить массив от повторяющихся элементов?

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

    const newArr = Array
      .from(arr.reduce((acc, n) => acc.set(n, (acc.get(n) ?? 0) + 1), new Map))
      .filter(n => n[1] === 1)
      .map(n => n[0]);

    Обновить существующий:

    arr.splice(0, arr.length, ...Array
      .from(arr.reduce((acc, n) => acc.set(n, acc.has(n)), new Map))
      .reduce((acc, n) => (n[1] || acc.push(n[0]), acc), [])
    );
    Ответ написан
  • Как из datetime-строки убрать секунды и запятую?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Знаю, что можно сделать с помощью split и прочими способами,...

    Если знаете - почему не показали? Никакой split не нужен:

    str.slice(0, -3).replace(',', '')

    Конечно, если очень хочется, то нет проблем его использовать:

    str.split(':', 2).join(':').split(',').join('')

    ...но нужно элегантное решение

    В данном случае оно может таким быть (или, по крайней мере, таким казаться):

    str.replace(/,|.{3}$/g, '')

    Но вообще, регулярные выражения - это не синоним элегантного решения:

    str.replace(/(\d+.\d+.\d+)..(\d+.\d+).*/, '$1 $2')
    Ответ написан
    Комментировать
  • Как найти максимальное количество повторений в массиве идущих подряд?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Math.max(0, ...arr.reduce((acc, n, i, a) => (
      n !== a[i - 1] && acc.push(0),
      acc[acc.length - 1]++,
      acc
    ), []))

    или

    arr.reduce((acc, n, i, a) => (
      n !== a[~-i] && (acc[1] = 0),
      acc[0] = acc[+(++acc[1] > acc[0])],
      acc
    ), [ 0, 0 ])[0]
    Ответ написан
    5 комментариев