Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Оцените решение задачки, пжл (https://javascript.ru/forum/misc/74647-ocenite-reshenie-zadachki-pzhl.html)

MC-XOBAHCK 26.07.2018 16:54

Оцените решение задачки, пжл
 
Читаю книжку "Выразительный JavaScript" и решаю каждую задачку из неё.
Проблема в том, что у меня ещё ни разу не совпало решение с решением автора.

Как пример задачка Реверсирование массива - написать функцию которая получает массив и отдаёт новый массив в котором элементы идут в обратном порядке.
Без проблем пишу такое решение:
function reverseArray(arr) {
    let newArr = [];
    for (let i = 0; i < arr.length; i++) {
        newArr[i] = arr[arr.length - 1 - i];
    }
    return newArr;
}


А вот вариант автора:
function reverseArray(array) {
    let output = [];
    for (let i = array.length - 1; i >= 0; i--) {
        output.push(array[i]);
    }
    return output;
}

У автора идёт логическое решение в условии цикла, а у меня же внутри цикла. Подобная картина со всеми задачками что я решал.

Посоветуйте, мне стоит переосмыслить стиль кода и делать как автор, прописывая логику в условии (думаю так тоже смогу, просто нужно некоторое время для адаптации и привыкания), или я нормально делаю и никакой разницы нет.
Просто я уже размечтался годика через два-три попробовать работать JS-программистом и пока прокачиваюсь знаниями, нужно и стиль подтягивать к тому как это делают профи.

j0hnik 26.07.2018 16:59

Цитата:

Сообщение от MC-XOBAHCK
Проблема в том, что у меня ещё ни разу не совпало решение с решением автора.

Это нормально автор решает экзотически, в этом задании отличия минимальны.

я б так решил
function reverseArray(arr) {
    return arr.map((el,i)=> arr[arr.length-1-i]);
}

j0hnik 26.07.2018 17:11

Там где то будут примеры которые автор решает несколькими способами:
1) двухэтажной рекурсией (много буков и медленно)
2) вложенным циклом (быстро и меньше буков)

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

MC-XOBAHCK 26.07.2018 17:21

Цитата:

Сообщение от j0hnik (Сообщение 491096)
я б так решил

Там в задачках оговаривается что без использования методов.

Я просто заметил что у меня всегда однотипная разница - у автора всегда логика в условие попадает.
Вот меня и взяло сомнение, может стоить правильно делать в его стиле, а то как я делаю не используется в серьёзной разработке.

j0hnik 26.07.2018 17:25

Цитата:

Сообщение от MC-XOBAHCK
Там в задачках оговаривается что без использования методов.

output.push(array[i]);
ох и автор :D

MC-XOBAHCK 26.07.2018 17:26

Цитата:

Сообщение от Rise
Это не в условии, условие там в середине, у автора естественно, у вас нет.

Правильно говорить "В параметрах цикла" ? или условиях?

Там в той книжке у него и в if() обычно логика засунута, вот я всё в кучу как условие определил, заметив что это как стиль написания кода идёт.

j0hnik 26.07.2018 17:29

for (инициализация; условие; выражение )

MC-XOBAHCK 26.07.2018 17:30

Цитата:

Сообщение от j0hnik
ох и автор

Это не автор, а я уже так накрутил. Имеется ввиду что работать по материалам пройденных глав. К тому же там времена var и map ещё не было. Короче как вы мне в прошлой теме написали - хочешь понять как это работает - возьми и напиши функцию.

MC-XOBAHCK 26.07.2018 17:34

Цитата:

Сообщение от j0hnik
for (инициализация; условие; выражение )

наверное я безнадёжен.

j0hnik 26.07.2018 17:35

MC-XOBAHCK,
сильно не загоняйтесь, стиль автора это не священный грааль, копировать не надо, извлекайте для себя полезное и пользуйтесь, не более того.

Dilettante_Pro 26.07.2018 17:43

Уж ежели автор использует push...
function reverseArray(array) {
    let output = [];
    do {
        output.push(array.pop());
    } while (array.length);
    return output;
}
alert(reverseArray([1,2,3,4,5]));


PS: лично мне естественней вариант автора, т.к. в задании -
Цитата:

Сообщение от MC-XOBAHCK
отдаёт новый массив в котором элементы идут в обратном порядке.

- ну и крути массив в обратном порядке.

MC-XOBAHCK 26.07.2018 17:52

Цитата:

Сообщение от j0hnik
сильно не загоняйтесь, стиль автора это не священный грааль, копировать не надо.

Цитата:

Сообщение от Rise
смотри на MDN for, там много ответов.

У меня хорошее понимание цикла for - вложенные циклы и сложная логика с ними внутри цикла меня не пугают и даже нравится такое решать.

Меня больше стиль кода интересует, где логику делать в параметрах или внутри. А то когда нить устроишься поработать, а "коллеги" спросят что за колхозный ниндзя код и сломают нос. А мне носик жалко, т.к. он у меня один.

Dilettante_Pro 26.07.2018 18:00

Цитата:

Сообщение от Rise
не, do здесь не очень, когда массив пустой

Ну и что? Пустой - он и в Африке пустой
function reverseArray(array) {
    let output = [];
    do {
        output.push(array.pop());
    } while (array.length);
    return output;
}
alert(JSON.stringify(reverseArray([])));

Хотя лучше, конечно, так
function reverseArray(array) {
    let output = [];
    while (array.length) {
        output.push(array.pop());
    } ;
    return output;
}
alert(JSON.stringify(reverseArray([])));

MC-XOBAHCK 26.07.2018 18:03

Наверное я непонятно спросил, меня решение той задачки не интересует.
Вот другая задачка автора книги:
Вызываем функцию
range(21, 54, 2)

она должна вернуть сумму чисел в диапазоне 1 и 2 параметра (21, 54), а третьий параметр - шаг чисел
// Сумма диапазона
function range(start, end, step = start < end ? 1 : -1) {
    let array = [];

    if (step > 0) {
        for (let i = start; i <= end; i += step) array.push(i);
    } else {
        for (let i = start; i >= end; i += step) array.push(i);
    }
    return array;
}

Вот у него опять в параметры пошла логика решения задачи (step =...). А я сделал решение где это внутри функции.
Меня этот стиль кодирования интересует.

MC-XOBAHCK 26.07.2018 18:08

Цитата:

Сообщение от Rise
ну логики туда много не засовывают, индексы только, обычно это сжиматели делают для минификации кода, вот они туда могут насувать прилично.

Во-во, у меня непонятки, то он понты так лепит или это общепринятый стиль у продвинутых проггеров. Я тоже хочу к продвинутым и готов подражать ихнему стилю если таков есть.

j0hnik 26.07.2018 18:09

родной реверс так работает, с обоих сторон фигачит =)
2 перестановки за итерацию
function reverse(array) {
  var j = array.length - 1;
  for (var i = 0; i < j; i++, j--) {
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

Dilettante_Pro 26.07.2018 18:37

Цитата:

Сообщение от Rise
присвоение в параметре функции

И, кстати, не работает.
function range(start, end, step = start < end ? 1 : -1) {
    let array = [];

    if (step > 0) {
        for (let i = start; i <= end; i += step) array.push(i);
    } else {
        for (let i = start; i >= end; i += step) array.push(i);
    }
    return array;
}
alert(range(54,21,2));

Это решение автора?

Nexus 26.07.2018 18:42

Dilettante_Pro, судя по комментарию функция должна была вообще сумму диапазона возвращать, а не сам диапазон...

MC-XOBAHCK 26.07.2018 18:54

Цитата:

Сообщение от Dilettante_Pro
Это решение автора?

Извините, это я напутал - эта функция возвращает только массив чисел в указанном диапазоне с шагом.
Вот полностью решение, там вторая функция (это практические задачки по закреплению пройденного материала):
// Сумма диапазона
function range(start, end, step = start < end ? 1 : -1) {
    let array = [];

    if (step > 0) {
        for (let i = start; i <= end; i += step) array.push(i);
    } else {
        for (let i = start; i >= end; i += step) array.push(i);
    }
    return array;
}

function sum(array) {
    let total = 0;
    for (let value of array) {
        total += value;
    }
    return total;
}
console.log(sum(range(1, 10)));  // → 55
console.log(range(5, 2, -1));    // [5, 4, 3, 2]


Спасибо всем за участие в этой непонятной теме.
В общем я понял что повторяющиеся вычисления в цикле если возможно выносим в условие, а в параметры функции - это уже понты.

Dilettante_Pro 26.07.2018 18:59

Nexus,
Да она ничего не возвращает - хоть сумму, хоть диапазон...

Nexus 26.07.2018 19:12

Dilettante_Pro, chrome v67.0.3396.99 возвращает массив.

MC-XOBAHCK 26.07.2018 19:13

Цитата:

Сообщение от Dilettante_Pro
Да она ничего не возвращает - хоть сумму, хоть диапазон...

Вот страница с этим решением http://eloquentjavascript.net/code/#4.1 (там кнопочка в самом низу Показать решение).

У меня работает и возвращает массив.

Nexus 26.07.2018 19:15

Меня логика в объявлении параметров и 2 почти одинаковых цикла подбешивают.
Я бы как-нибудь так лучше сделал (не знаю как условие сократить, а очень хочется):
function range(start, end, step) {
    step = step !== undefined ? step : (start < end ? 1 : -1);
    let array = [];

    for (let i = start; step > 0 && i <= end || step < 0 && i >= end; i += step)
        array.push(i);


    return array;
}

рони 26.07.2018 19:15

MC-XOBAHCK,
Сумма диапазона, а без циклов решение сможешь?

Nexus 26.07.2018 19:22

рони, с шагом отличным от 1?

рони 26.07.2018 19:36

Nexus,
с любым шагом 1,2,5,-7,-1 ... условие одно, никаких циклов

Alexandroppolus 26.07.2018 19:36

рони,
через рекурсию?

рони 26.07.2018 19:38

Nexus,
alert(fun(10,1,-1));
alert(fun(1,10,1));
alert(fun(10,1));
alert(fun(1,10));
все вызовы вернут 55

рони 26.07.2018 19:39

Alexandroppolus,
без рекурсии

MC-XOBAHCK 26.07.2018 19:41

Цитата:

Сообщение от рони
Сумма диапазона, а без циклов решение сможешь?

да, есть же reduce в JS.

Alexandroppolus 26.07.2018 19:42

рони,
т.е. дан массив, индексы начала и конца, шаг, и надо найти сумму элементов, без цикла, рекурсии, всяких трюков с setInterval и т.д.? Синхронным кодом? Методы массивов использовать можно?

рони 26.07.2018 19:42

:) смотрите пост №28 Nexus,
уберите циклы и верните сумму

рони 26.07.2018 19:45

Цитата:

Сообщение от Alexandroppolus
Методы массивов использовать можно?

если это не цикл типа reduce и прочих, не знаю что может пригодится из этих методов.

Alexandroppolus 26.07.2018 19:47

а, теперь понял.
Тут всё в кучу, в этом топике )
сумма арифметической прогрессии, в общем. По формуле все вычисляется

рони 26.07.2018 19:48

Цитата:

Сообщение от Alexandroppolus
т.е. дан массив,

нет , только начало, предел и шаг

рони 26.07.2018 19:48

Цитата:

Сообщение от Alexandroppolus
По формуле все вычисляется

:yes: :dance:

MC-XOBAHCK 26.07.2018 20:00

Цитата:

Сообщение от рони (Сообщение 491141)
:yes: :dance:

end * (end + 1) * 0.5
только с шагом это не прокатит.

рони 26.07.2018 20:24

сумма арифметической прогрессии
 
MC-XOBAHCK,
function fun(start, end, step) {
    step = step || (start > end ? -1 : 1);
    var n = (end - start) / step | 0;
    return (start + n * step / 2) * ++n
}
alert(fun(10, 1, -1));
alert(fun(1, 10, 1));
alert(fun(10, 1));
alert(fun(1, 10));

https://javascript.ru/forum/misc/731...-shagom-2.html

MC-XOBAHCK 26.07.2018 21:02

рони,
не, так бы я точно не смог.

Я начал просто вот так в столбик расписывать и приводить к формуле:
n +
(n + 1) +
(n + 2) +
(n + 3) +
(n + 4) +
(n + 5)
=
n + n * (1 + 2 + 3 + 4 + 5 + ........);

получается в скобках выражение заходит под формулу: end * (end + 1) * 0.5, но в ней end = end - start

start + start * ((end - start) * (end - start + 1) * 0.5)

Это получилась формула для последовательных чисел, если не наделал ошибок.
А как к ней шаг прикрутить я завис без каких либо идей.

+++++++++++++
Запустил на тест и сразу вижу 2 ошибки когда n выносил как множитель в прорисовке макета формулы.
n * (1 + 2 + 3 + 4 + 5 + 6 + ........);

MC-XOBAHCK 26.07.2018 21:25

Ошибки разобрал. Вот такая получается функция суммы последовательных чисел если делать через арифметическую формулу:
function sum(start, end) {
    return start * ((end - start + 1) * (end - start + 2) * 0.5);
}
console.log(sum (1, 4));  // 10

!!! Функция работает НЕПРАВИЛЬНО!!! Где то ошибка в формуле, не могу понять.
console.log(sum(2, 5));


Часовой пояс GMT +3, время: 10:42.