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

JS Pierwsza powtarzająca się liczba ze zbioru w tablicy

Object Storage Arubacloud
+1 głos
3,077 wizyt
pytanie zadane 27 marca 2018 w JavaScript przez TerryCrow Początkujący (340 p.)

Cześć, mam takie zadanie, którego treść wklejam poniżej a pod nim nawet wkleiłem kod który to zadanie rozwiązuje, jednak nie do końca go rozumiem. Czy jest (to znaczy na pewno jest :) ) jakiś inny lepszy sposób na rozwiązanie tego zadania? Podpowiecie coś? Jestem początkujący więc bardzo bym prosił o coś co byłoby mi łatwiej zrozumieć. Widzę u siebie że najsprawniej uczę się gdy analizuję jakiś kod tylko najpierw potrzebuję zrozumieć co dokładnie w nim zachodzi i dlaczego akurat tak a nie inaczej. Będę wdzięczny za każdą podpowiedź.

TREŚĆ ZADANIA

W pliku script.js stwórz tablicę z 10 dowolnymi liczbami (niech kilka będzie takich samych) oraz zmienną firstIndex. W pętli for sprawdź, która z liczb powatarza się jako pierwsza i przypisz jej indeks do zmiennej firstIndex. Następnie wypisz w konsoli tą zmienną, poza pętlą for.

Przykładowa tablica:

 var arrWithNumbers = [2,4,5,2,3,5,1,2,4];

W tej tablicy jako pierwsza powtarza się liczba 2, więc zmienna firstIndex powinna mieć wartość 0, ponieważ jest to pierwsza liczba w tablicy, która ma gdzieś swojego sobowtóra. Przetestuj Twój skrypt z różnymi wartościami w tablicy. Podpowiedź: pamiętaj o odpowiednim przerwaniu pętli.

KOD - ROZWIĄZANIE ZADANIA:

var firstIndex = "";
var arrWithNumbers = [1,4,21,55,87,40,55,32,90,2];

for (var i=0; i < arrWithNumbers.length; i++) {
    for (var j = i+1; j < arrWithNumbers.length; j++) {
        if (arrWithNumbers[i] === arrWithNumbers[j]){

            if(firstIndex === ""){

                firstIndex = arrWithNumbers.indexOf(arrWithNumbers[i]);
                break;
            }
        }
    }

    if(firstIndex !== ""){

        break;
    }
}
console.log("Indeks pierwszej powtorzonej liczby z tablicy to: ", firstIndex);

 

komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)
a tak z ciekawości to skąd masz te wszystkie zadanka do nauki JS?

Dobrze, że uczysz się JS od takich rzeczy - wiele osób traktuje dziś JS jak język wyłącznie do stronek www itp. i od razu myślą o animacjach itp. Fajnie, że chcesz się nauczyć faktycznie czystego języka, jego składni porządnie itp.

Tak dalej, powodzenia!
komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)
Staram się o przyjęcie do jednej ze szkół programowania i żeby się dostać to muszę nauczyć się podstaw JSa właśnie poprzez robienie zadań tego typu. Dlatego zależy mi na tym aby dobrze to zrozumieć a nie tylko przepisywać kody bezmyślnie. Pewnie przez to zadaję czasem głupie pytania ale generalnie do tej pory siedziałem w raczej humanistycznych tematach i przez to tak ciężko mi to ogarnąć.
komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)

Pewnie przez to zadaję czasem głupie pytania

Nie zadajesz, powiem nawet, że jesteś jedną z nielicznych osób zaczynających naukę, które dają nie tylko treść zadania i "chcę gotowca" ale próbują sami to rozwiązywać, za co u mnie masz duży plusik.

 do tej pory siedziałem w raczej humanistycznych tematach

Jest tu na forum jeden humanista... chyba najbardziej ceniony JS developer, mający nawet na koncie książkę o JS:)

komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)
Dzięki za miłe słowo. Może kiedyś coś ze mnie będzie ale na razie czuję że po prostu czytam Wasze odpowiedzi, początek już zaczynam rozumieć a gdzieś w trakcie się gubię i cały sens tego kodu mi ucieka.
komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)

@TerryCrow, A jeszcze taka mała uwaga... Ty przypisujesz początkowo do zmiennej firstIndex pusty ciąg "", a potem podmieniasz to na liczbę, reprezentującą index elementu.

To nie do końca dobra praktyka. Co prawda w JS można zmieniać typ wartości zmiennej, ale lepiej jest jednak pilnować jednego typu. Dlatego lepsze wg mnie byłoby zadeklarowanie bez wartości początkowej czyli let firstIndex, co de facto zwróci w razie odwólania się do zmiennej wartość undefined.

A dlaczego nie zero? Ano dlatego, że gdyby w tablicy nie było żadnego zdublowanego elementu to w tej zmiennej błędnie przechowywalibyśmy zero jako teoretyczny indeks pierwszego elementu. Teraz to pewnie oczywiste, ale warto pamiętać o takich niuansach bo czasem mogą przysporzyć sporo problemów logicznych w aplikacji :)

4 odpowiedzi

+1 głos
odpowiedź 27 marca 2018 przez Snejki Stary wyjadacz (14,520 p.)

 

Pierwsza pętla for iteruje po kolei nasze i  zaczynając od 0, dopóki i jest mniejsze od rozmiaru tablicy:

for (var i=0; i < arrWithNumbers.length; i++)

Druga pętla rozpoczyna iterację od  i+1, czyli jeżeli pierwszy for ma w danym momencie indeks 3, to druga pętla rozpoczyna pracę od 4. 

 for (var j = i+1; j < arrWithNumbers.length; j++)

Następnie warunek if porównuje elementy tablicy, na które wskazują iteratory obu pętli

if (arrWithNumbers[i] === arrWithNumbers[j])

jeżeli ich wartości są sobie równe to sprawdzamy czy firstindex, nie ma juz przypisanej wartości:

if(firstIndex === "")

Jeżeli firstindex jest pusty to przypisujemy mu iterator i, a następnie przerywamy wykonywanie środkowej(Drugiej) pętli, jeżeli firstindex ma już jakąś wartość przypisaną, to kontynuujemy działanie pętli wewnętrznej(Drugiej).

 firstIndex = arrWithNumbers.indexOf(arrWithNumbers[i]);
 break;

Po zakończeniu iteracji pętli wewnętrznej for(Drugiej), lub jej przerwaniu breakiem, sprawdzamy czy firstindex ma przypisaną jakąś wartość i jeśli ma to przerywamy wykonywanie pętli zewnętrznej(Pierwszej), w innym wypadku pętla zewnętrzna(Pierwsza) for wykona kolejną iterację, lub przerwie pętlę, gdy i == rozmiar tablicy

 if(firstIndex !== ""){
 
        break;
    }


 

+1 głos
odpowiedź 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)
edycja 27 marca 2018 przez Tomek Sochacki

Można też inaczej podejść do problemu, wg mnie prościej przynajmniej na początku nauki:

let firstIndex;
const arr1 = [1,4,21,55,87,40,55,32,90,2];

for(let i = 0; i < arr1.length; i += 1) {
	const n = arr1[i];
	if(arr1.indexOf(n) !== arr1.lastIndexOf(n)) {
		firstIndex = i;
		break;
	}
}

console.log('Indeks: ' + firstIndex + ', czyli liczba: ' + arr1[firstIndex]);
//Indeks: 3, czyli liczba: 55

Generalnie idea jest taka, że iterujmy po tablicy i badamy, czy dany "current" element ma sobowtóra, czyli czy indeks pierwszego napotkania np. 55 jest równy indeksowi ostatniego napotkania (szukając od końca tablicy). Jeśli znaleźliśmy element występujący co najmniej dwa razy to kończymy zabawę i wpisujemy jego indeks w zmienną.

Moim zdaniem to jest czytelniejsze rozwiązanie od tego co przedstawiłeś.

Można też pobawić się np. Array.prototype i zrezygnować z pętli for:

const arr = [1,4,21,55,87,40,55,32,90,21,2];

const firstIndex = arr.findIndex((val, index, array) => {
	return index !== array.lastIndexOf(val);
});
undefined

firstIndex; //2

Ale to tak bardziej dla ciekawostki, bo w zadaniu masz jasno napisane o pętli for.

komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)

Ok, ten przykład faktycznie wydaje się łatwiejszy tylko nie rozumiem tu dlaczego stworzone zostało const n = arr1[i] i co dokładnie robi ten warunek: 

if(arr1.indexOf(n) !== arr1.lastIndexOf(n)) {

        firstIndex = i;

Nawet nie wiem jak to ująć w słowa... chodzi mi o to że skoro operator !== oznacza "jest różne od" to jakim sposobem znajduje to dwie takie same liczby w tej tablicy...? Serio strasznie się w tym plączę :/

komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)
Poczytaj w dokumentacji MDN o metodzie indexOf oraz lastIndexOf. Specjalnie nie daję linka, to zadanie domowe żeby zapoznać się co to i poszperać trochę po dokumentacji MDN :)

Tak w dużym skrócie indexOf szuka pierwszego elementu, od początku tablicy, a lastIndexOf szuka ostatniego, czyli przeszukuje tablicę od końca. Dlatego jeśli jest tylko jeden element to znaleziony od początku i od końca ma ten sam indeks, natomiast jeśli są co najmniej dwa to te indeksy są różne.

A co do tego const to tak dodatkowo, aby nie szukać dwa razy w tablicy elementu arr[i], w sumie na razie może być bez tego, tak trochę odruchowo to napisałem.
komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)
http://poradnik.drogimex.pl/2017/04/27/przeszukiwanie-tablic-w-javascript-przeglad-wybranych-metod/

Tutaj pisałem kiedyś co nie co o przeszukiwaniu tablic, może te przykłady co nie co rozjaśnią :)
komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)
Dziękuję Ci, zaraz sobie to przejrzę
komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)

@Tomek Sochacki, a skoro dzięki tej metodzie lastIndexOf możemy przykładowo podejrzeć ostatnią liczbę ze zbioru to czy przy wykorzystaniu tej metody możemy również wypisać wszystkie liczby z tablicy zaczynając od końca? Jest jakiś taki sposób? np żeby zamiast pisania tak:

var tablica = [3,76,1,90,78,66,75,99,12,30];
for (var i= tablica.length; i >= 0; i--) {
    console.log(tabSet[i]);
}

napisać to jakoś z wykorzystaniem właśnie lastIndexOf?

komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)

@Tomek Sochacki, A jeszcze jedno :) Powiedziałeś że to const n zostało napisane trochę odruchowo i mogłoby tego nie być. W takim razie gdybyśmy mieli to wyrzucić to jak miałby wyglądać ten kod żeby działał bez tego?

komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)

Co do pytania o odwracanie tablicy to można też inaczej:

const arr = [1,2,3,4,5];

arr.reverse(); //[5, 4, 3, 2, 1]
arr; //[5, 4, 3, 2, 1]

Tylko uwaga, bo metoda reverse() modyfikuje bazową tablicę, aby tego uniknąć można by np. użyć dodatkowo metody slice() - jak dojdziesz do nauki metod tablicowych to wróć sobie do tego przykładu :)

Z tą pomocniczą zmienną "n" chodzi o to, aby nie szukać dwa razy elementu o indeksie "i" tylko wyszukać raz i zapamiętać. Pozwala to nieco przyspieszyć działanie pętli i jednocześnie ułatwia ewentualne modyfikacje logiki jeśli byłoby więcej operacji na aktualnym elemencie tablicy. A żeby kod działał bez tego to po prostu w miejsce gdzie ja wstawiam zmienną Ty podaj odniesienie do elementu tablicy.

1
komentarz 27 marca 2018 przez niezalogowany

Ja mam czasem wrażenie, że tylko chodzę i się czepiam : P

const firstIndex = arr.findIndex((val, index, array) => {
    return array.indexOf(val) !== array.lastIndexOf(val);
});

array.indexOf(val) to po prostu index

komentarz 27 marca 2018 przez Tomek Sochacki Ekspert (227,510 p.)

Ja mam czasem wrażenie, że tylko chodzę i się czepiam : P

Chodź więcej i czepiaj się więcej :) Poprawiłem w moim przykładzie gdyby ktoś kiedyś chciał tu jeszcze zajrzeć...

Tak dla wyjaśnienia dla autora posta - tutaj metoda findIndex zwróci nam indeks pierwszego elementu spełniającego kryterium (a dokładniej elementu, dla którego callback function zwróci true). Iterujemy więc po kolei po elementach i po napotkaniu pierwszego, który jest zdublowany jego index będzie oczywiście jak pisze kolega argeento równy temu, który zwróciłaby metoda indexOf.

0 głosów
odpowiedź 27 marca 2018 przez BT101 Stary wyjadacz (12,540 p.)
edycja 27 marca 2018 przez BT101

Da radę stworzyć lepszy kod, tzn taki, który nie będzie miał algorytmu O(n^2) czyli pętli w pętli. Ogólnie pętla w pętli jest wolna bo przy każdym obrocie pętli zewnętrznej program musi przejechać po pętli wewnętrznej.

Aczkolwiek nie wiem czy taki kod będzie dla Ciebie prostrzy ;)

var arr = [1,4,21,55,87,40,55,32,90,2];

function lookForDuplicates(array) {
    var values = Object.create(null);
    for (var i = 0, l = array.length; i < l; i++) {
        var value = array[i];
        if (value in values) {
            return array.indexOf(value);
        }
        values[value] = true;
    }
    return false;
}

console.log(lookForDuplicates(arr));

A tutaj demo.

komentarz 27 marca 2018 przez TerryCrow Początkujący (340 p.)
Dziękuję za przykład, jednak faktycznie prostszy to on dla mnie nie jest :)
0 głosów
odpowiedź 27 marca 2018 przez Artek Stary wyjadacz (11,800 p.)
Stwórz dodatkową tablicę. Np. w tablicy o indeksie 7 będzie zliczana ilość pojawień się liczby 7. Jeżeli liczba pojawień równa się dwa zwróć wartość indeksu. Będzie jedna pętla tylko.

Podobne pytania

0 głosów
1 odpowiedź 351 wizyt
pytanie zadane 23 października 2019 w C i C++ przez Olfux Nowicjusz (120 p.)
0 głosów
2 odpowiedzi 155 wizyt
pytanie zadane 15 sierpnia 2018 w JavaScript przez warzywko13 Użytkownik (840 p.)
0 głosów
6 odpowiedzi 1,182 wizyt
pytanie zadane 21 sierpnia 2016 w C i C++ przez newgu123 Początkujący (260 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 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!

...