const elements = Array.prototype.filter.call(
document.querySelectorAll('.green'),
(n, i, a) => n.nextElementSibling !== a[i + 1]
);'.green + .green', или при фильтрации дополнительно проверяйте, что n.previousElementSibling === a[i - 1].
str.split('/').pop()
// или
str.match(/[^\/]+$/)[0]
// или
str.replace(/.*\//, '')
// или
str.slice(str.lastIndexOf('/') + 1)
// или
Array.from(str).reduce((acc, n) => n === '/' ? '' : acc + n, '')
// или
[...str].filter((n, i, a) => !a.includes('/', i)).join('')
const itemSelector = '.header';
const buttonSelector = `${itemSelector} .delete_block`;document.querySelectorAll(buttonSelector).forEach(function(n) {
n.addEventListener('click', this);
}, ({ currentTarget: t }) => {
while (!(t = t.parentNode).matches(itemSelector)) ;
t.replaceWith();
});
// или
document.addEventListener('click', e => e
.target
.closest(buttonSelector)
?.closest(itemSelector)
.remove()
);
function merge(key, ...arrs) {
const getKey = key instanceof Function ? key : n => n[key];
const result = new Map;
arrs.forEach(arr => arr.forEach(n => {
const k = getKey(n);
result.set(k, Object.assign(result.get(k) ?? {}, n));
}));
return [...result.values()];
}const result = merge('id', arr1, arr2, arr3);.
const getTruthyKeys = obj =>
Object
.entries(obj)
.filter(n => n[1])
.map(n => n[0]);for([key, value] of Object.entries(item)) {const obj = new Proxy({
a: 0,
b: 1,
c: 2,
}, {
get: () => Math.round(Math.random()),
});console.log(Array.from({ length: 10 }, () => getTruthyKeys(obj)));
const replaceValues = (val, test, replacer, key) =>
test(key, val)
? replacer(val)
: val instanceof Object
? Object.entries(val).reduce((acc, [ k, v ]) => (
acc[k] = replaceValues(v, test, replacer, k),
acc
), val.constructor())
: val;function replaceValues(val, test, replacer) {
const stack = [];
const clones = new Map;
const getClone = (v, k) =>
test(k, v)
? replacer(v)
: v instanceof Object
? (clones.has(v) || stack.push([ v, clones.set(v, v.constructor()).get(v) ]),
clones.get(v))
: v;
if (val instanceof Object) {
for (getClone(val); stack.length;) {
const [ source, target ] = stack.pop();
for (const k in source) if (Object.hasOwn(source, k)) {
target[k] = getClone(source[k], k);
}
}
}
return getClone(val);
}const newData = replaceValues(
data,
k => k?.endsWith('Date'),
v => v.replace(/(\d+)-(\d+)-/, '$2.$1.')
);
$('.content_toggle').click(function() {
const $button = $(this);
$(`#box-${this.id.split('-').pop()}`).slideToggle(300, function() {
const isHidden = $(this).is(':hidden');
$button
.text(isHidden ? 'Показать текст' : 'Скрыть текст')
.toggleClass('open', !isHidden);
});
return false;
});$(this).closest('здесь селектор общего предка').find('.content_block')$(this).next()$('.content_block').eq($('.content_toggle').index(this))
$(document).on('click', 'a[id^="answer_"]', e => $(`#comment_${e.target.id}`).toggle());
function setNested(root, ...args) {
const val = args.pop();
const key = (args = args
.flat(Infinity)
.flatMap(n => typeof n === 'string' ? n.split('.') : n))
.pop();
args.reduce((p, c) => p[c] ??= {}, root)[key] = val;
}setNested(data, '0.arr.0.str', 'hello, world!!');
setNested(data, 0, 'arr', 1, 'num', 666);Интересуют готовые решения
Нужно изменить этот массив, преобразовав все строки с датами в нём, независимо от того, как глубоко они вложены, в объекты.
const replaceNested = (val, replacer) =>
val instanceof Object
? Object.entries(val).reduce((acc, [ k, v ]) => (
acc[k] = replaceNested(v, replacer),
acc
), val.constructor())
: replacer(val);const newData = replaceNested(
data,
x => typeof x === 'string' && /^\d{2}\.\d{2}\.\d{4}$/.test(x)
? new Date(x.split('.').reverse().join('-'))
: x
);
const valueKey = 'number';
const percentKey = 'percent';const sum = arr.reduce((acc, n) => acc + n[valueKey], 0);
const getPercent = n => n[valueKey] / sum * 100;const newArr = arr.map(n => ({ ...n, [percentKey]: getPercent(n) }));
// или
arr.forEach(n => n[percentKey] = getPercent(n));
Object
.entries(arr.reduce((acc, n) => (
n = n.match(/('.*?'):'(.*?)'/),
(acc[n[1]] ??= []).push(n[2]),
acc
), {}))
.map(n => `${n[0]}:'${n[1].join('|')}'`)
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.3.4/cdn.min.js"></script>
<div x-data="{
items: [
{ id: 69, text: 'hello, world!!' },
{ id: 187, text: 'fuck the world' },
{ id: 666, text: 'fuck everything' },
],
}">
<template x-for="(n, i) in items">
<div>
<span x-text="n.text"></span>
<button @click="items.splice(i, 1)">x</button>
</div>
</template>
</div>
Код, который работает некорректно...
Object.freeze назначить новое свойство уже не получится. Можно записать итератор в прототип массива (ну и после того, как он отработает, вернуть оригинальный итератор на место):const originalIterator = Array.prototype[Symbol.iterator];
Array.prototype[Symbol.iterator] = function() {
let i = -1;
return {
next: () => (i += 2) < arr.length
? { done: false, value: this[i] }
: { done: true },
};
};
setTimeout(() => Array.prototype[Symbol.iterator] = originalIterator, 0);
const result = arr.flat();
// или
const result = Array.prototype.concat.apply([], arr);
// или
const result = arr.reduce((acc, n) => (acc.push(...n), acc), []);
// или
const result = [];
for (const n of arr) {
for (const m of n) {
result[result.length] = m;
}
}
const outerClass = 'filter__item';
const innerClass = 'filter__checkgroup-count';OUTER:
for (const n of document.getElementsByClassName(outerClass)) {
for (const m of n.getElementsByClassName(innerClass)) {
if (Number(m.innerText)) {
continue OUTER;
}
}
n.hidden = true;
// или
n.style.display = 'none';
// или
n.style.setProperty('visibility', 'hidden');
// или
n.style.cssText += 'opacity: 0';
// или
n.setAttribute('style', 'transform: scale(0)');
}.hidden {
display: none;
}document.querySelectorAll(`.${outerClass}`).forEach(n => {
n.classList.toggle('hidden', !Array.prototype.some.call(
n.querySelectorAll(`.${innerClass}`),
m => +m.textContent
));
});
function isEqual(a, b) {
const keysA = Object.keys(a);
const keysB = Object.keys(b);
return keysA.length === keysB.length && keysA.every(n => a[n] === b[n]);
}
const result = arr1.concat(arr2.filter(n => arr1.every(m => !isEqual(n, m))));const unique = function(arr, keys = n => n) {
const picked = new Map;
return arr.filter((...args) => {
const p = []
.concat(keys(...args))
.reduce((acc, k) => acc.set(k, acc.get(k) ?? new Map).get(k), picked);
return !p.set(this, p.has(this)).get(this);
});
}.bind(Symbol());
const result = unique([ ...arr1, ...arr2 ], n => [ n.teamId, n.userId ]);
const zip = (...arrs) =>
arrs[0]?.map((n, i) => arrs.map(m => m[i])) ?? [];
const result = zip(arr1, arr2);const zip = (arrs, defaultValue = null) =>
Array.from(
{ length: Math.max(...arrs.map(n => n.length)) },
(n, i) => arrs.map(m => i < m.length ? m[i] : defaultValue)
);
// или
const zip = (arrs, defaultValue = null) =>
arrs.reduce((acc, n, i) => (
n.forEach((m, j) => (acc[j] ??= Array(arrs.length).fill(defaultValue))[i] = m),
acc
), []);const result = zip([ arr1, arr2 ]);.zip([ [ 1, 2, 3 ], [], [ 99 ] ], Infinity) - в результате получим[
[ 1, Infinity, 99 ],
[ 2, Infinity, Infinity ],
[ 3, Infinity, Infinity ]
]function* zip(data, defaultValue = null) {
const iterators = Array.from(data, n => n[Symbol.iterator]());
for (let doneAll = false; doneAll = !doneAll;) {
const values = [];
for (const n of iterators) {
const { value, done } = n.next();
values.push(done ? defaultValue : value);
doneAll &&= done;
}
if (!doneAll) {
yield values;
}
}
}const result = [...zip([ arr1, arr2 ])];.Array.from(zip((function*() {
yield [ , true, false, NaN ];
yield 'abcde';
yield Array(3).keys();
})()))[
[ undefined, 'a', 0 ],
[ true, 'b', 1 ],
[ false, 'c', 2 ],
[ NaN, 'd', null ],
[ null, 'e', null ]
]
const chunked = (arr, chunkSize) =>
arr.reduce((acc, n, i) => (
(i % chunkSize) || acc.push([]),
acc.at(-1).push(n),
acc
), []);
console.log(chunked([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 3));const group = (data, key) =>
Array.prototype.reduce.call(
data,
(acc, n, i, a) => ((acc[key(n, i, a)] ??= []).push(n), acc),
{}
);
const chunked = (data, chunkSize) =>
Object.values(group(data, (_, i) => i / chunkSize | 0));
console.log(chunked('0123456789', 3));
console.log(chunked(document.querySelectorAll('img'), 5));const chunked = (data, chunkSize, slice = data.slice) =>
Array.from(
{ length: Math.ceil(data.length / chunkSize) },
function(_, i) {
return this(i * chunkSize, (i + 1) * chunkSize);
},
(slice instanceof Function ? slice : Array.prototype.slice).bind(data)
);
console.log(chunked('abcdefghij', 4)); // так кусками будут тоже строки
console.log(chunked('abcdefghij', 4, [].slice)); // а так - массивы
console.log(chunked($('img'), 5));function* chunked(data, chunkSize) {
let chunk = [];
for (const n of data) {
if (chunk.push(n) === chunkSize) {
yield chunk;
chunk = [];
}
}
if (chunk.length) {
yield chunk;
}
}
console.log(Array.from(chunked([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 3)));
console.log([...chunked(document.querySelectorAll('img'), 5)]);
for (const n of chunked(Array(10).keys(), 4)) {
console.log(n);
}