• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Fukcja z tablicami

Object Storage Arubacloud
0 głosów
385 wizyt
pytanie zadane 21 lipca 2017 w JavaScript przez modest Nowicjusz (210 p.)

Mam taką funkcję do zrobienia, ktoś ma jakiś pomysł?

Napisz funkcję bigestSumOfTwoElements(array), która przyjmuje tablicę z liczbami i zwraca sumę dwóch największych elementów z tej tablicy. Dla uproszczenia możemy założyć, że przekazana tablica zawiera wyłącznie liczby.

  • Jeżeli tablica zawiera tylko jeden element, funkcja powinna zwrócić wartość tego elementu.
  • Jeżeli tablica zawiera zero elementów, funkcja powinna zwrócić wartość logicznąfalse.

Przykład:

bigestSumOfTwoElements([1,2,3,4]) // => 7
bigestSumOfTwoElements([]) // => false
bigestSumOfTwoElements([76]) // => 76
bigestSumOfTwoElements([23,45,17,12]) // => 68

3 odpowiedzi

+1 głos
odpowiedź 21 lipca 2017 przez Tomek Sochacki Ekspert (227,510 p.)
edycja 21 lipca 2017 przez Tomek Sochacki

coś takiego?

const bigestSumOfTwoElements = arr => !arr.length ? false : arr.sort((a,b) => b-a).slice(0,2).reduce((a,b) => a+b,0);

Krok 1: jeśli pusta tablica to FALSE

Krok 2: sortuj elementy od max do min

Krok 3: wytnij max dwa pierwsze elementy tablicy

Krok 4: sumuj 1 lub 2 uzyskane elementy

Ale uważam, że dla pustej tablicy lepszym rozwiązaniem jest zwrócenie wartości zero niż false, żeby nie mieszać typów zwracanej wartości. Jest to jedna z zasad w tzw. programowaniu funkcyjnym, która jest dobrą praktyką, zobacz sobie np. metodę indexOf - zwraca albo znaleziony indeks albo wartość -1, ale zawsze masz pewność, że uzyskasz zwrotnie liczbę. Takie podejście pozwala łatwiej pracować z funkcjami, gdy wiesz jakiej wartości się spodziewać.

komentarz 21 lipca 2017 przez modest Nowicjusz (210 p.)
chyba nie do końca
komentarz 21 lipca 2017 przez Tomek Sochacki Ekspert (227,510 p.)
ale co wg Ciebie działa nieprawidłowo? Wszystkie Twoje testy przechodzą poprawnie.

Podaj przykład testu który się załamuje to zobaczymy, bo być może nie podałeś wszystkich wytycznych.
komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)
I to jest doskonały przykład, czemu nie lubię FP. Nikt mi nie wmówi, że ten kod jest bardziej czytelny od "tradycyjnego" :P
komentarz 21 lipca 2017 przez Tomek Sochacki Ekspert (227,510 p.)
mógłbyś rozwinąć skrót "FP"?

A dlaczego uważasz, że mój kod jest nieczytelny? Kolejno wywołuję 3 podstawowe metody Array.prototype, które wydawało mi się, że jasno wskazują jaki w danym miejscu chcę osiągnąć cel.

Co być radził poprawić, aby kod był wg Ciebie bardziej czytelny? Oczywiście nie robiłem tu żadnej walidacji danych wejściowych ale zadanie wyraźnie wskazywało że zawsze dostajemy tablicę zawierającą liczby.
1
komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)

FP – Functional Programming

Chodzi mi o sam sposób zapisu. Stworzenie "strumienia" funkcji, które przekazują sobie nawzajem wartość, i zapisanie go w jednej linii przy użyciu arrow functions z pominięciem nawiasów i klamr sprawia, że całość jest niepotrzebnie nieczytelna. A przecież zapis:

const bigestSumOfTwoElements = ( arr ) => {
	if ( arr.length === 0 ) {
		return false;
	} 

	return arr.sort( ( a, b ) => {
		return b - a;
	} ).slice( 0, 2 ).reduce( ( a, b ) => {
		return a+b;
	}, 0 );
};

jest o wiele czytelniejszy (nawet bez rozpisywania arrowów w taki sposób). Nie widzę sensu w agresywnym wykorzystywaniu właściwości arrow functions i omijaniu return + pchaniu wszystkiego w jedno wyrażenie – bo nie ma to żadnego sensu. Ba, główną funkcję zadeklarowałbym normalnie, a jedynie dla anonimowych callbacków wewnątrz zostawił strzałkowe.

komentarz 21 lipca 2017 przez Tomek Sochacki Ekspert (227,510 p.)
Ok, niech będzie, choć nadal uważam, że zapisanie tego w jednej linii przy tak nieskomplikowanych operacjach nie wpływa bardzo mocno na czytelność ale oki, kwestia stylu.

A powiedz mi dlaczego uważasz, że zapis !arr.length jest nieczytelny? Wydaje mi się, że jest on chyba dla każdego jasny, szczególnie, że w JS zasady konwersji do true/false nie są mocno skomplikowane.
komentarz 21 lipca 2017 przez mokrowski Mędrzec (155,460 p.)
E tam, trochę się uprzedzasz do FP. W każdym wydaniu "fanatyzm" jest toksyczny. Po pierwsze mamy do czynienia z JavaScript który ma taki sobie (oj byłem oględny) projekt języka a po drugie sam "strumień funkcji" nie jest tożsamy z podejściem FP.

Tak naprawdę to jeśli funkcja zwraca wynik lub błąd, to mamy do czynienia z typem optional który w poważnych (i dobrze zaprojektowanych) językach jest jawnie zdefiniowany a w JavaScript i np. C to "jawna proteza". Jakieś "magiczne" -1, zera (bo akurat jest poza poprawnym wynikiem), wyjątki czy jakieś "globalne errno" :-)
komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)

Ok, niech będzie, choć nadal uważam, że zapisanie tego w jednej linii przy tak nieskomplikowanych operacjach nie wpływa bardzo mocno na czytelność ale oki, kwestia stylu.

I Twój kod jest czytelniejszy od mojego? ;)

 E tam, trochę się uprzedzasz do FP. W każdym wydaniu "fanatyzm" jest toksyczny. Po pierwsze mamy do czynienia z JavaScript który ma taki sobie (oj byłem oględny) projekt języka a po drugie sam "strumień funkcji" nie jest tożsamy z podejściem FP.

I to jest kolejny argument, podnoszony zwłaszcza przez użytkowników "poważniejszych" języków funkcyjnych, który powoduje, że nie używam FP w JS: JS jest złym językiem do stosowania FP. No skoro jest, to czemu wszyscy próbują FP w nim używać? I tak, mam świadomość, że uprościłem samo pojęcie. 

komentarz 21 lipca 2017 przez ScriptyChris Mędrzec (190,190 p.)
edycja 21 lipca 2017 przez ScriptyChris

Moim zdaniem, kod @Tomasz Sochacki bez zbytniego rozbudowywania, można zrobić bardziej czytelnym - głównie przez umieszczenie kolejnych wywołań metod w nowych liniach.

const bigestSumOfTwoElements = ( arr ) => {
	return !!arr.length && arr.sort( ( a, b ) => b - a )
           		              .slice( 0, 2 )
						      .reduce( ( a, b ) => a + b, 0 );
};

Zamiast ternary operator można zastosować OR AND, który zwróci flagę false, jeśli tablica jest pusta, a w przeciwnym razie wykonają się metody.

Jakie zastosowanie ma przecinek w wyrażeniu a + b, 0? Z tego co czytam, to pozwala wykonać kilka wyrażeń i zwrócić ostatnie. Więc, czy zwracasz w .reduce() zero?

[edit]

Ah, brak klamer mnie zmylił. Dopiero po kodzie @Comandeer zorientowałem się, że ", 0" to jest drugi parametr, a nie "hack z dodatkowym operatorem w postaci przecinka". Metoda reduce jako drugi parametr przyjmuje wartość inicjalną, stąd przecinek i zero.

komentarz 21 lipca 2017 przez Tomek Sochacki Ekspert (227,510 p.)
myślałem nawet o takim rozwiązaniu z przerzuceniem metod do nowych linii tylko że tak sobie teraz myślę, że nie przejdzie to kontroli kodu np. ESLint - ale to już kwestia jaki kto obiera styl pisania.

Co do !!arr.length to faktycznie, nie pomyślałem o tym - dobry pomysł :)
+1 głos
odpowiedź 21 lipca 2017 przez kap Stary wyjadacz (11,620 p.)

Jak już się bawić w FP to lepiej tak:

xD

 

// Compose na szybko napisany, można użyć np lodashowego
const compose = (...args) => val => args
  .reduce((a, b) => b(a), val)

// Funkcje pomocnicze

const sortNumbersDesc = arr => arr.sort((a, b) => b - a)

const sumElements = arr => arr.reduce((a, b) => a + b, 0)

const sliceFromStart = numberOfElements => arr => arr.slice(0, numberOfElements)

// Główna funkcja (uogólniona)

const sumBiggestElements = numberOfElements => arr => compose(
  sortNumbersDesc,
  sliceFromStart(numberOfElements),
  sumElements
)(arr)

// Uszczegółowienie funkcji

const sumTwoBiggestElements = sumBiggestElements(2)

// "Testy :P"

console.log('1:', sumTwoBiggestElements([1,2,3,4]) === 7)
console.log('2:', sumTwoBiggestElements([]) === 0)
console.log('3:', sumTwoBiggestElements([76]) === 76)
console.log('4:', sumTwoBiggestElements([23,45,17,12]) === 68)

 

https://codepen.io/caderek/pen/przgeB?editors=0012

komentarz 21 lipca 2017 przez kap Stary wyjadacz (11,620 p.)

Lepiej @Comandeer ? :D

komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)
Tak, przynajmniej rozwiałeś moje wątpliwości, czemu faktycznie nie stosuję FP w większości przypadków :v
komentarz 21 lipca 2017 przez kap Stary wyjadacz (11,620 p.)
:D A tak serio to co tam nieczytelnego (pomijając pisanego na szybko composa, który zresztą powinien być wbudowany), bo główną funkcję czyta się jak opis algorytmu wg mnie ;)
komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)
No jest to o wiele czytelniejsza wersja.

Niemniej nie przekonuje mnie sama koncepcja. Wydaje mi się, że tego typu podejście do problemu go po prostu komplikuje.
komentarz 21 lipca 2017 przez kap Stary wyjadacz (11,620 p.)
edycja 21 lipca 2017 przez kap
No w JSie może trochę prawda, ale ogólnie takie podejście jest wg mnie ok, warunek - trzeba być oswojonym z FP, a o to niestety ciężko w zespole. Także taki kod piszę głównie "rekreacyjnie" ;)
komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)
Jest OK, pytanie jest inne: czy jest na tyle OK, żeby powiedzieć "to teraz piszemy funkcyjnie, najlepiej zero obiektówki"? Bo jak na razie FP w kontekście JS dla mnie wygląda po prostu jak kolejny hype.
komentarz 21 lipca 2017 przez kap Stary wyjadacz (11,620 p.)
Jak masz ludzi, którzy to lubią, rozumieją i jest to dla nich czytelne (kwestia przyzwyczajenia, o ile piszę się małe,uniwersalne funkcje, nie tasiemce jak w pierwszej odpowiedzi) to mozna próbować. Aczkolwiek mnie JS też czasem wkurza, przez toporność i braki w FP (niby wszystko można osiągnąć, ale nie tak ładnie jak chociażby w Clojure, F#). Ale wprowadzanie FP w zespole OOP lub mieszanym to głupi pomysł (choć elementy i idee FP warto przemycać).
komentarz 21 lipca 2017 przez Comandeer Guru (600,730 p.)
Właśnie wszyscy powtarzają "warto", "jest lepiej", ale nikt nie podaje suchych faktów. Warto – czemu? Podawane przykłady są zwykle oderwane od rzeczywistości, a szkoda.
0 głosów
odpowiedź 21 lipca 2017 przez Jedras Maniak (54,860 p.)
Najpierw sprawdziłbym ilość elementów w tablicy. Jak jest zero to zwróć false, jak jest jeden to zwroc ten o zerowym indexie (czyli ten jedyny). Jeśli jest więcej niż jeden to szukasz w tablicy największy element i zapisujesz do zmiennej. Później robisz drugi raz to samo tylko sprawdzasz czy ta liczba jest różna od tej z pierwszej zmiennej.

Podobne pytania

0 głosów
1 odpowiedź 132 wizyt
0 głosów
1 odpowiedź 172 wizyt
pytanie zadane 23 kwietnia 2020 w JavaScript przez maslokeeper01 Użytkownik (620 p.)
0 głosów
0 odpowiedzi 404 wizyt
pytanie zadane 7 marca 2019 w JavaScript przez makarony Nowicjusz (120 p.)

92,539 zapytań

141,382 odpowiedzi

319,476 komentarzy

61,928 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...