$grouped = [];
foreach ($arr as [ 'id' => $id, 'name' => $name, 'key' => $key ]) {
$grouped[$key][$name] ??= [ 'name' => $name, 'ids' => [] ];
$grouped[$key][$name]['ids'][] = $id;
}
foreach ($keys as $k) {
$$k = array_map(fn($n) => [
'name' => $n['name'],
'ids' => implode(', ', $n['ids'])
], array_values($grouped[$k] ?? []));
}
Здесь я отвлекусь, и порассуждаю на тему того, что на самом деле тестирование - это гораздо более трудоёмкая задача, чем обычно считается. И как следствие, большая часть тестов - это такая вот туфта. Либо тест заранее возвращает нужные данные, либо тестирует один-два кейса. А вариантов неправильных входящих данных ведь может быть огромное количество. То есть по-хорошему на такой заведомо сложный (и принципиально неделимый!) метод нужно десятка два тестов.
И сюда же использование для тестов БД другой системы. Например основная БД MySQL, а для тестов используется Sqlite. Тут сразу можно сказать, что это профанация. Различие даже в какой-то одной настройке БД может повлиять на результаты запроса (и теста как следствие) - а тут и вовсе используется совсем другая БД.
С другой стороны, работу с БД скорее стоит тестировать не в юнит тестах, а скажем в интеграционных. Но не будем углубляться.
$len = mb_strlen($string);
$counts = array_count_values(mb_str_split($string));
foreach ($counts as $letter => $count) {
echo "$letter: " . round($count / $len * 100, 1). "\n";
}
colors: markerColors, // Устанавливаем цвета маркеров в зависимости от результата
discrete
, позволяющим индивидуально настраивать внешний вид каждого маркера. Всплывающую подсказку это никак не затрагивает, так что её придётся кастомизировать отдельно. Я выполняю 2 одинаковых запроса
Bitmap Index Scan on ix_friends_user_id (cost=0.00..61.56 rows=5465 width=0) (actual time=0.742..0.743 rows=88 loops=1)
const filteredProducts = computed(() => {
const search = searchQuery.value.toLowerCase();
return search.length > 2
? data.value.filter(n => n.title.toLowerCase().includes(search))
: null;
});
<ul v-if="filteredProducts" class="search-result">
<li v-if="!filteredProducts.length">
<h3>ничего не найдено</h3>
</li>
<li v-for="n in filteredProducts">
<div>
<Image :src="n.image" :alt="n.title" width="40" height="40" />
</div>
<h3>{{ n.title }}</h3>
<div>
<p>{{ n.price }}</p>
</div>
</li>
</ul>
v-for
.// если гарантируется отсутствие thead и tfoot, или их содержимое также должно учитываться
const { rows } = table;
// если tbody один
const [ { rows } ] = table.tBodies;
// если tbody несколько
const rows = Array.prototype.flatMap.call(table.tBodies, n => [...n.rows]);
// или
const rows = [].concat(...Array.from(table.tBodies, n => [...n.children]));
// или
const rows = table.querySelectorAll('tbody tr');
const middle = arr => arr[arr.length >> 1];
// или
const middle = arr => arr[Math.floor(arr.length / 2)];
// или
const middle = arr => arr[Math.round(~-arr.length / 2)];
// или
const middle = arr => arr[(arr.length - arr.length % 2) / 2];
const cell = middle(middle(rows).cells);
// или
const cell = middle([].reduce.call(rows, (acc, n) => (acc.push(...n.children), acc), []));
// или, без получения строк
const cell = middle(table.querySelectorAll('tbody td'));
const el = document.querySelector('p');
const strings = [ 'hello, world!!', 'fuck the world', 'fuck everything' ];
const delay = 100;
function Typewriter(el, strings, delay) {
let i = 0;
let length = 0;
return setInterval(() => {
if (++length > strings[i].length) {
i = -~i % strings.length;
length = 0;
}
el.textContent = strings[i].slice(0, length);
}, delay);
}
const intervalId = Typewriter(el, strings, delay);
// хотим остановить, делаем так: clearInterval(intervalId);
function Typewriter(el, strings, delay) {
let timeoutId = null;
(function step(i, length) {
length = -~length % -~strings[i].length;
i = (i + !length) % strings.length;
el.innerText = strings[i].substring(0, length);
timeoutId = setTimeout(step, delay, i, length);
})(0, 0);
return () => clearTimeout(timeoutId);
}
const stop = Typewriter(el, strings, delay);
// хотим остановить, делаем так: stop();
// [object NodeList] (7)
[#text,<div/>,#text,<div/>,#text,<div/>,#text]
Так вот у этих текстовых узлов нет параметра offsetWidth, соответственно вы складываете undefined, получая NaN.- let box = document.querySelector(".box").childNodes;
+ let box = document.querySelector(".box").children;
- box.forEach((item) => {
+ for (let item of box) {
- })
+ }
function getCombinations($arr, $keys = [], $vals = []) {
return ($n = $arr[count($keys)] ?? null)
? array_merge(...array_map(
fn($k) => getCombinations(
$arr,
[ ...$keys, $k ],
[ ...$vals, ...$n[$k] ]
),
array_keys($n)
))
: [ implode('_', $keys) => $vals ];
}
const blocks = ref(Array.from({ length: 5 }, (_, i) => (-~i) ** 2));
const active = ref(0);
function next() {
active.value = (active.value + 1 + blocks.value.length) % blocks.value.length;
}
let intervalId = null;
onMounted(() => intervalId = setInterval(next, 500));
onUnmounted(() => clearInterval(intervalId));
<div
v-for="(n, i) in blocks"
v-text="n"
:class="[ 'box-item', { active: i === active } ]"
></div>
:nth-child
- не круто. Лучше сделать компонент, принимающий массив цветов и создающий блоки на его основе. Соответственно, вместо класса будет назначаться цвет фона напрямую, как-то так:<div
v-for="(n, i) in colors"
:style="{ backgroundColor: i === active ? n : '' }"
...