Привет!
спасибо за такую подсказку, я дня 3 ходил вокруг да около, но сам не допёр, пришлось использовать твою подсказку чтобы дальше пройти.
На мой взгляд задача довольно сложная(
вопрос!
почему использовалось let вместо привычного var?
а точнее, где когда используют одно а где другое?
прочитал бегло пару статей, но толком не понял
скажешь - ну прочитай не бегло))) - а смыысла нет для меня, там примеры с какими-то окнами приводятся, пока не проходил окна, не знаю что это)
про let и const можно почитать тут.
уже давно они стали стандартом в индустрии, просто курсы учат ванильному js, который хоть и лежит в основе современного языка, но не применяется уже либо просто кому-то влом переделывать старое. у var на самом деле достаточно всяких косяков, которые жизнь усложняют.
читается так: если объект не содержит ключ, который называется “элемент массива с индексом i”, то присвоить такому ключу значение 1, иначе инкремент этого ключа.
при всем при этом, если такого ключа не было в объекте, то мы его тут же на месте создаем и присваиваем ему значение.
чтобы было проще понять - объект, это поименованный кусок кода, который содержит коллекцию ключ-значение, таких пар может быть от нуля и до бесконечности.
Классное решение! Которое “простой” вариант!
У меня немного по другому реализовано, но смысл примерно тот же. Опирался на уже пройденный материал курса.
var getRepeats = function (array) {
var object = {};
for (var i = 0; i < array.length; i++) {
if (array.indexOf(array[i]) === i) {
var repeatNumber = 1;
for (var j = i+1; j < array.length; j++) {
if(array[i] === array[j]) {
repeatNumber++;
}
}
object[array[i]] = repeatNumber;
}
}
return object;
};
Получилось достаточно объемно, а ваше решение просто огонь!
знаете в чем принципиальная разница между нашими кодами? (ну помимо быстродействия и ресурсоемкости)
вы аккумулируете значения из массива, я же подставляю ключи в объект с запросом на уникальность.
что я имею ввиду - у нас будут разные результаты в нестандартных ситуациях. например, попробуйте вызвать функцию с почти пустым массивом, с ненулевой длиной. например [,,,"рыба",,"рыба",,]. как можете удостовериться - длина этого массива - 7.
что из этого правильнее - я хз =) но легче мой скрипт
P.S. Спасибо, я стараюсь для форума =)
Сделал вот так, достаточно легко читается, как мне кажется:
var getRepeats = function (words) {
var obj = {};
for (var i = 0; i < words.length; i ++) {
obj[words[i]] = 0;
}
for (var i = 0; i < words.length; i ++) {
obj[words[i]] += 1;
}
return(obj);
};
Кто-нибудь может объяснить, почему запись obj[ words[i] ] работает,
а запись obj.words[i] не работает?
Я предложу три варианта. Начинаем традиционно с гавнокода:
// 1
var getRepeats = function (data) {
var obj = {}; // создаём пустой объект
var usedWords = []; // создаём пустой массив, в который будем записывать слова, которые уже использовались
for (var i = data.length; i--; ){ // цикл от больше к меньшему. Когда i-- === 0, то цикл прекращается
if (usedWords.indexOf( data[i] ) == -1) { // Если текущего слова нет в массиве использованных слов, его индекс === -1, тогда выполняем следующие действия
usedWords.push(data[i]); // Тогда добавляем это новое слово в массив использованных слов
obj[data[i]] = 0; // Также добавляем его в объект со значением 0
for (var j = data.length; j--; ){
if(data[i] == data[j]) obj[data[i]]++; // Перебираем массив ещё раз и ищем сколько раз встречается слово, и добавляем к свойству объекта единицу
} // Завершили цикл
} // Завершили условие
} // Завершили цикл
return obj;
}
// 2 С точки зрения сайта, вот такое стандартное решение
var getRepeats = function (data) {
var obj = {};
for (var i = data.length; i--; ){
obj[data[i]] = 0;
for (var j = data.length; j--; ){
if (data[j] === data[i]) obj[data[i]]++;
}
}
return obj;
}
// 3 Я тут погуглил, нашёл вот такую хрень массив.filter(x => x === массив[i]).length , и адаптировал под свой скрипт. Работает, но я пока не совсем понимаю как работает.
var getRepeats = function (data) {
var obj = {};
for (var i = data.length; i--; ){
obj[data[i]] = data.filter(x => x === data[i]).length;
}
return obj;
}
фильтр не нужен. неоптимально. лучший это через инкремент фор или редьюс
как работает тут фильтр: на каждой итерации формируется массив одинаковых элементов и его длина записывается в ключ объекта. неоптимально тем, что каждую итерацию создается новый безымянный массив и по нескольку раз идет перебор одного и того же ключа в случае повтора
а можете объяснить почему это работает, а не вываливается в Timeout error?
Насчёт фильтр спасибо, не знал. Про редьюс я ещё ничего не знаю, ни разу это не практиковал.
Разницы между for (var i = data.length; i--; ){ ...}
и for (var i = 0; i < data.length;i++){ ...}
с первого взгляда нет,
но в одном из видео на ютубе Sorax сказал, что способ с инркементом медленнее, чем способ с декрементом
Он это объяснил тем, что меньше операций совершается при каждом круге цикла. Программист он не глупый)
Вываливается в Timeout error ? Нет, конечно. Я все скрипты тестировал.
ну разница во внутренней реализации for++ и for--. опираться на мнение какого-то программера конечно здорово, но вы можете самостоятельно провести бенчмарк с замером времени в момент вызова и окончания в момент выдачи результата.
в большинстве современных браузеров (т.е. это не сложности цикла зависит, а от движков браузеров) for++ быстрее работает. в последнее время его вытесняет filter и reduce по быстродействию.
нет, я не говорю что вываливается с ошибкой, я спрашиваю почему не вываливается, потому что не понимаю что является условием выхода из цикла. т.е. это норм работает применительно к массивам, так? т.е. в последней итерации он получает arr.length = -1, получает отказ как нереферентное значение (т.к. length от 0 до индекса последнего элемента +1) и спокойно завершает цикл, я так понял.
upd: вроде доперло,
цикл for работает так:
получает первый шаг i = arr.length и это известно до 1 итерации
пост-итерационное действие отсутствует, тут просто. интересна серединка:
далее он проверяет возвращает ли true выражение i = i - 1, т.е. не является ли результат вычисления нулем (грубо)
на последней итерации, поскольку это постфиксный декремент, он в условие возвращает 1, уменьшается на единицу, передает в цикл 0, там совершаются какие-то операции с i == 0 и перед следующей итерацией оно снова проверяет i = i - 1, которое возвращает 0 и завершает цикл. Гениально.
и что интересно, на 1ой итерации цикла происходят операции с последним элементом массива, т.к. в цикл возвращается уже arr.length - 1, что и есть индекс последнего элемента массива.
но честно говоря, мне туда еще рано соваться. как минимум нужно свободно понимать reduce, filter, map и RegExp чтобы не городить километровые простыни кода (как это делают тут на форуме)
а так пока “учуся” xD