const countWithKey = (arr, key) => arr.filter(n => key in n).length;
console.log(countWithKey(arr, 'ключ'));
const sum = (data, val = n => n) =>
Array.prototype.reduce.call(
data,
(acc, n) => acc + val(n),
0
);
console.log(sum(arr, obj => obj.hasOwnProperty('ключ')));
sum([ 1, 2, 3 ]) // 6
), так и более сложные варианты. Например, есть массив, представляющий содержимое корзины с товарами (цена, количество), надо посчитать общую стоимость:const cart = [
{ price: 100, count: 5 },
{ price: 10, count: 6 },
{ price: 1, count: 7 },
];
const total = sum(cart, item => item.price * item.count); // 567
const likes = sum(document.querySelectorAll('.btn_like .btn__counter'), n => +n.innerText);
function Counter(data, key = n => n) {
const counted = new Map;
for (const n of data) {
const k = key(n);
counted.set(k, (counted.get(k) ?? 0) + 1);
}
return k => counted.get(k) ?? 0;
}
const keyExists = Counter(arr, obj => Object.hasOwn(obj, 'ключ'));
console.log(keyExists(true)); // смотрим, у скольких элементов массива ключ есть
console.log(keyExists(false)); // и у скольких нет
const str = 'hello, world!!';
const chars = Counter(str);
console.log(chars('h')); // 1
console.log(chars('!')); // 2
console.log(chars('x')); // 0
const persons = [
{ name: 'Вася', birthday: new Date('1999-05-22') },
{ name: 'Маша', birthday: new Date('2004-03-06') },
{ name: 'Катя', birthday: new Date('1976-05-15') },
{ name: 'Петя', birthday: new Date('1987-04-18') },
{ name: 'Коля', birthday: new Date('2000-01-01') },
{ name: 'Дима', birthday: new Date('2003-05-09') },
{ name: 'Миша', birthday: new Date('1996-02-29') },
{ name: 'Таня', birthday: new Date('1981-03-12') },
{ name: 'Олег', birthday: new Date('1992-08-24') },
];
const birthMonths = Counter(
persons,
({ birthday }) => birthday.toLocaleString('ru-RU', { month: 'long' })
);
console.log(birthMonths('май')); // в мае родилось три человека
console.log(birthMonths('март')); // в марте два
console.log(birthMonths('октябрь')); // а в октябре никто
function* naturalNumbers(n) {
for (let i = 1; i <= n; i++) {
yield i;
}
}
const numLengths = Counter(naturalNumbers(100), num => `${num}`.length);
console.log(numLengths(2)); // среди первых ста натуральных чисел - девяносто двухзначных
console.log(numLengths(3)); // и одно трёхзначное
console.log(numLengths(0)); // число из нуля знаков? - конечно же нет таких
function objToString(val, tabSize = 2, depth = 0, noIndent = false) {
const indent = ' '.repeat(tabSize * depth);
return (noIndent ? '' : indent) + (
val instanceof Array
? `[\n${val.map(n => objToString(n, tabSize, depth + 1)).join(',\n')}\n${indent}]`
: val instanceof Object
? `{\n${Object
.entries(val)
.map(n => n.map((m, i) => objToString(m, tabSize, depth + 1, i)).join(': '))
.join(',\n')}\n${indent}}`
: typeof val === 'string'
? `"${val}"`
: val
);
}
console.log(objToString({
numbers: [ 69, 187, 666 ],
strings: [ 'hello, world!!', 'fuck the world', 'fuck everything' ],
falsy_values: [ 0, '', NaN, false, null, undefined ],
object: { xxx: true, yyy: Infinity, zzz: { '!&$': [ [ [ -1 ] ] ] } }
}));
вторая не работает
.grade-item
обрабатывать, а только те, у кого тот же родитель, что и у кликнутого:document.querySelector('.nav-student-new-lesson').addEventListener('click', e => {
if (e.target.classList.contains('grade-item')) {
const items = [...e.target.parentNode.children];
const grade = 1 + items.indexOf(e.target);
const color = [
[ 5, 'rgba(150, 255, 0, 0.3)' ],
[ 3, 'rgba(255, 150, 0, 0.3)' ],
[ 1, 'rgba(255, 0, 0, 0.3)' ],
].find(n => n[0] <= grade)[1];
items.forEach((n, i) => n.style.background = i < grade ? color : 'white');
}
});
const listEl = document.querySelector('#list');
const activeClass = 'active';
let index = 0;
next(0);
document.addEventListener('keydown', function(e) {
const step = ({
ArrowDown: 1,
ArrowUp: -1,
})[e.key];
if (step) {
next(step);
}
});
function next(step) {
const elems = listEl.children;
elems[index].classList.remove(activeClass);
index = Math.max(0, Math.min(elems.length - 1, index + step));
// или, если надо, чтобы при переходе от последнего к следующему элементу
// активным становился первый, а при переходе от первого к предыдущему
// активным становился последний
// index = (index + step + elems.length) % elems.length;
elems[index].classList.add(activeClass);
}
const result = unique(arr, n => n.user.id);
.const unique = (arr, key) =>
Object.values(Object.fromEntries(arr.map(n => [ key(n), n ])));
// или, если в результирующий массив должны попадать те из "одинаковых" элементов,
// что расположены в исходном массиве первыми
const unique = (arr, key) =>
Object.values(arr.reduce((acc, n) => (acc[key(n)] ??= n, acc), {}));
// или, если надо также сохранять взаимное расположение элементов
const unique = (arr, key) =>
arr.filter(function(n) {
const k = key(n);
return !(this[k] = this.hasOwnProperty(k));
}, {});
Map
и Set
:const unique = (arr, key) =>
Array.from(new Map(arr.map(n => [ key(n), n ])), n => n[1]);
// или (в отличие от объекта, Map запоминает порядок вставки,
// так что тут взаимное расположение элементов сохраняется)
const unique = (arr, key) =>
[...arr.reduce((acc, n) => {
const k = key(n);
return acc.set(k, acc.get(k) ?? n);
}, new Map).values()];
// или
const unique = (arr, key) =>
arr.filter(function(n) {
const k = key(n);
return !this.has(k) && this.add(k);
}, new Set);
const radios = document.querySelectorAll('[name="radios"]');
const selects = Array.from(radios, n => n.nextElementSibling);
const onChange = e => selects.forEach(n => n.disabled = n !== e.target.nextElementSibling);
radios.forEach(n => n.addEventListener('change', onChange));
const arithmeticProgression = ({ length, a1 = 0, d = 1 }) =>
Array.from(
{ length },
(n, i) => a1 + i * d
);
const arr = arithmeticProgression({
length: 10,
a1: 6,
d: 3,
});
function* arithmeticProgression(a1, d, length) {
for (let i = 0; i < length; i++) {
yield a1 + i * d;
}
}
for (const n of arithmeticProgression(100, 10, 5)) {
console.log(n);
}
console.log(Array.from(arithmeticProgression(10, -7, 10)));
const voidTags = [ 'input', 'img', 'br', 'hr', ещё какой-то тэг, и ещё, ... ];
function createHTML(data) {
const attrs = Object
.entries(data.attrs ?? {})
.map(n => `${n[0]}="${n[1]}"`)
.join(' ');
const startTag = `<${data.tagName}${attrs && (' ' + attrs)}>`;
if (voidTags.includes(data.tagName)) {
return startTag;
}
const children = (data.subTags ?? [])
.map(createHTML)
.join('');
return `${startTag}${data.text ?? ''}${children}</${data.tagName}>`;
}
arr.map((n, i, a) => a.slice(0, i + 1).join(''))
// или
arr.reduce((acc, n) => (acc.push((acc.at(-1) ?? '') + n), acc), [])
(function xxx(arr, str = '') {
if (str.length === arr.length) {
return [];
}
const newStr = str.concat(arr[str.length]);
return [ newStr, ...xxx(arr, newStr) ];
})(arr)
overlay.click(e => {
if (e.target === e.delegateTarget) {
overlay.fadeOut();
}
});
// или
overlay.click(function(e) {
$(this).filter(e.target).fadeOut();
});
overlay
.click(() => overlay.fadeOut())
.children()
.click(e => e.stopPropagation());
$.each($.parseJSON(response), (k, v) => $(`.${k}`).text(v));
for (const [ k, v ] of Object.entries(JSON.parse(response))) {
document.querySelector(`.${k}`).innerText = v;
}
document.querySelector('.listing').after(...arrayWords.map(n => {
const p = document.createElement('p');
p.innerHTML = n;
return p;
}));
// или
document.querySelector('.listing').insertAdjacentHTML('afterend', arrayWords
.map(n => `<p>${n}</p>`)
.join('')
);
arrayWords.reduce((prev, n) => {
const p = document.createElement('p');
p.innerHTML = n;
prev.after(p);
return p;
}, document.querySelector('.listing'));
$('table').on('change', 'select', ({ target: t }) => {
$(t).replaceWith(t.value);
// или
$(t).parent().text(t.value);
});
document.querySelector('table').addEventListener('change', ({ target: t }) => {
if (t.tagName === 'SELECT') {
t.parentNode.replaceChild(document.createTextNode(t.value), t);
// или
t.parentNode.textContent = t.value;
}
});
progress.css('background-color', [
{ min: 100, color: '#47C965' },
{ min: 40, color: '#f5dd30' },
{ min: 0, color: '#bf4542' },
].find(n => n.min <= strength).color);
const tests = [ здесь перечисляете регулярные выражения ].map((n, i) => ({
regex: n,
message: error_wrap.attr(`data-error_${i + 1}`),
}));
const newArr = Object
.values(arr.reduce((acc, n, i) => ((acc[n] ??= []).push(i), acc), {}))
.reduce((acc, n) => (n.forEach(i => acc[i] = n.length > 1), acc), []);
// или
const newArr = arr.map(function(n) {
return this[n];
}, arr.reduce((acc, n) => (acc[n] = acc.hasOwnProperty(n), acc), {}));
// или
const count = arr.reduce((acc, n) => (acc[n] = (acc[n] ?? 0) + 1, acc), {});
const newArr = arr.map(n => count[n] > 1);
// или
const newArr = arr.map((n, i, a) => a.indexOf(n) !== a.lastIndexOf(n));
arr.forEach(function(n, i, a) {
a[i] = this.get(n) > 1;
}, arr.reduce((acc, n) => acc.set(n, -~acc.get(n)), new Map));
// или
const duplicates = arr.reduce((acc, n) => acc.set(n, acc.has(n)), new Map);
arr.splice(0, arr.length, ...arr.map(n => duplicates.get(n)));
$('select').change(function() {
const text = $(':checked', this).text();
console.log(text);
});
document.querySelector('select').addEventListener('change', function(e) {
const select = this;
// или
// const select = e.target;
// const select = e.currentTarget;
const option = select.selectedOptions[0];
// или
// const option = select.options[select.selectedIndex];
// const option = select.querySelector(':checked');
// const option = [...select.children].find(n => n.selected);
const text = option.text;
// или
// const text = option.textContent;
// const text = option.innerText;
console.log(text);
});
document.querySelector('#filter-input').addEventListener('input', e => {
const val = e.target.value.toLowerCase();
container.querySelectorAll('.title').forEach(n => {
n.closest('.card').style.display = n.innerText.includes(val)
? 'block'
: 'none';
});
});
const obj = Object.fromEntries(arr.map((n, i) => [ `answer${i + 1}`, n ]));
const obj = arr.reduce((acc, n, i) => (acc['answer' + ++i] = n, acc), {});
const obj = {};
for (let i = 0; i < arr.length; i++) {
obj['answer'.concat(-~i)] = arr[i];
}
str[0] === str[0].toUpperCase()
/^[A-Z]/.test(str)
(c => 64 < c && c < 91)(str.charCodeAt(0))
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.includes(str.at(0))
$('.filter').change(({ target: t }) => {
$(`[name="${$(t).closest('.button').data('size')}"]`)
.closest('.product-box')
.toggleClass('hidden', !t.checked);
}).find(':checked').change();
const filter = document.querySelector('.filter');
filter.addEventListener('change', ({ target: t }) => {
const size = t.closest('.button').dataset.size;
document.querySelectorAll(`[name="${size}"]`).forEach(n => {
n.closest('.product-box').classList.toggle('hidden', !t.checked);
});
});
filter.querySelectorAll(':checked').forEach(n => {
n.dispatchEvent(new Event('change', { bubbles: true }));
});