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

Przekształcenie tablicy w specyficzny obiekt

Object Storage Arubacloud
+1 głos
351 wizyt
pytanie zadane 7 stycznia 2018 w JavaScript przez Janusz92 Bywalec (2,150 p.)

Witam.

Mam problem z przekształceniem tablicy na obiekt w określony sposób:

Tablica którą posiadam:

[5, 2, 430.1794455479025]
[5, 4, 455.87184657079644]
[4, 1, 503.85164417598463]
[4, 3, 354.66577212546935]
[3, 2, 229.77966449378414]
[3, 1, 513.7192612106761]
[2, 1, 349.2653565073386]
[2, 0, 494.33272496892874]
[1, 0, 223.40573843780768]

Chciałbym przekształcić na obiekt tego typu:

var x = {
	5:{2:430.1794455479025,4:455.87184657079644},
	4:{1:503.85164417598463,3:354.66577212546935,5:455.87184657079644},
	3:{2:229.77966449378414,1:513.7192612106761,4:354.66577212546935},
	2:{1:349.2653565073386,0:494.33272496892874,5:430.1794455479025,3:229.77966449378414},
	1:{0:223.40573843780768,4:503.85164417598463,3:513.7192612106761,2:349.2653565073386},
	0:{2:494.33272496892874,1:223.40573843780768},
}

Pierwsza i druga kolumna w tablicy to id vertexów, a trzecia stanowi odległość pomiędzy nimi. Chciałbym to przerobić na powyższy obiekt, w którym będą zawarte wszystkie wierzchołki razem z połączeniami jako kolejne zagnieżdżenie.

Uproszczając, obiekt można czytać jako: "z 5 można się dostać do 2 i 4", "z 4 można się dostać do 1, 3 i 5" itd.

Niestety nieco się zamuliłem z rozwiązaniem tego problemu :) Z góry dziękuję za pomoc.

komentarz 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)
A to nie jest czasem trochę bez sensu? - dublujesz dane dla poszczególnych par.

3 odpowiedzi

+2 głosów
odpowiedź 7 stycznia 2018 przez ScriptyChris Mędrzec (190,190 p.)

Na przykład w ten sposób:

var obj = {};

arr.forEach( ( innerArr ) => {
	var iA0 = innerArr[ 0 ];
	var iA1 = innerArr[ 1 ];
	var iA2 = innerArr[ 2 ];
	
	if ( !obj[ iA0 ] ) {
		obj[ iA0 ] = { [ iA1 ]: iA2 };
    } else {
		obj[ iA0 ][ iA1 ] = iA2;
    }

	if ( !obj[ iA1 ] ) {
        obj[ iA1 ] = { [ iA0 ]: iA2 };
    } else {
        obj[ iA1 ][ iA0 ] = iA2;
    }
} );

Mój sposób zadziała, jeśli pewne jest, że każda z tablic jest 3 elementowa. W przeciwnym razie trzeba wstawić więcej warunków. Skrypt polega na tym, że iterujesz po każdej tablicy i od razu zapełniasz obiekt - przy czym sprawdzasz, czy property z nowym kluczem istnieje, czy nie. W zależności od tego tworzysz nowy zagnieżdżony obiekt, albo dodajesz nowe property do wcześniej utworzonego obiektu. Kluczami są najpierw pierwszy, a poźniej drugi element tablicy.

Jeśli masz pytania, to śmiało.

P.S. Możesz zamienić var na const, żeby było bardziej ES6.

1
komentarz 7 stycznia 2018 przez Tomek Sochacki Ekspert (227,510 p.)

P.S. Możesz zamienić var na const, żeby było bardziej ES6.

To jak już Kolega Janusz chciałby bawić się w ES6 to można też skorzystać z zapisu:

const [iA0, iA1, iA2] = innerArr;

i jedną linijką stworzyć trzy zmienne :)

komentarz 7 stycznia 2018 przez ScriptyChris Mędrzec (190,190 p.)
O, nawet nie wiedziałem, że nie trzeba bezpośrednio podawać nazwy elementu, aby skorzystać z tego zapisu. :) Zbyt rzadko z tego bajeru korzystam.
komentarz 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)

@Krzycho92, Nazwy zmiennych miodzio :P

komentarz 8 stycznia 2018 przez ScriptyChris Mędrzec (190,190 p.)
Myślę, że jak na przykładowy kod, nazwy zmiennych są dosyć czytelne.
komentarz 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)
Wg mnie przykładowy kod nie powinien odbiegać jakością od kodu produkcyjnego - w końcu chcesz wytłumaczyć coś komuś. Ale niech będzie, że się czepiam.
komentarz 8 stycznia 2018 przez ScriptyChris Mędrzec (190,190 p.)

Zanim kod trafi na produkcję poddawany jest z reguły code review. Przechodzi też przez testy. Dlatego moim zdaniem jakość kodu wstawianego na forum w celu wyjaśnienia zagadnienia lub pomocy z konkretnym problemem nie jest istotna na takim samym poziomie, jak kod który pisze się w pracy. Oczywiście, zawsze warto pisać jak najlepszy kod. Na forum zazwyczaj jednak dajesz wskazówkę jak dany problem rozwiązać; przedstawiasz swoje podejście, które niekoniecznie musi być najlepsze. Zawsze można w komentarzu podpowiedzieć, co można poprawić - choćby tak jak wyżej zrobił @Tomek Sochacki.

Natomiast, jeśli już zwracasz uwagę, że czyjś kod nie jest najlepszy, to podaj swoją propozycję.

komentarz 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)
edycja 8 stycznia 2018 przez kap

Prosze bardzo:
 

const [iA0, iA1, iA2] = innerArr

można zamienić na np:
 

const [vertexA, vertexB, distance] = edge

I już jest o niebo lepiej, bez skrótowców.

 

Zanim kod trafi na produkcję poddawany jest z reguły code review.

Tak, ale to nie oznacza by pierwszej wersji nie przygotować najlepiej jak umiemy :) Btw na code review też byś pewnie dostał taką uwagę (no może bardziej profesjonalną w stylu "daj jakieś opisowe, nieskrótowe nazwy zmiennych") - jak reviewer widzi skopane nazwy zmiennych, to nie wymyśla lepszych, tylko odsyła kod (chyba, że nie szanuje swojego czasu).

 

Przechodzi też przez testy.

Nie widzę związku.

komentarz 8 stycznia 2018 przez ScriptyChris Mędrzec (190,190 p.)

Tak, ale to nie oznacza by pierwszej wersji nie przygotować najlepiej jak umiemy :) 

W takim razie może mam za małe doświadczenie, bo zdarza mi się poprawiać kod kilka razy - a to można coś skrócić, a to faktycznie poprawić nazewnictwo, albo zmienić nieco podejście na bardziej optymalne. Niemniej, na forum czasami odpowiedź pisze się na szybko zajmując się w tym czasie czymś innym, albo z telefonu (co nie jest wygodne). Czy wtedy ważna jest perfekcyjna składnia, czy raczej to aby faktycznie komuś pomóc pokazując przykładowe rozwiązanie danego problemu? Nie przesadzałbym tutaj z perfekcjonizmem - choć jak napisałem wcześniej, warto zawsze starać się pisać jak najlepszy kod, aby nie zapominać o dobrych nawykach.

komentarz 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)
No i spoko. Nazwy utrudniły mi prześledzenie Twojego rozwiązania stąd ten komentarz.

PS
Optymalny się nie stopniuje (niezłośliwa uwaga!).
0 głosów
odpowiedź 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)
edycja 9 stycznia 2018 przez kap

Ogólnie to co tam masz to książkowy przykład grafu nieskierowanego z wagami ( wiki ) i tak optymalnie byłoby to zaimplementować (nie tak straszne jak brzmi, są do tego gotowe biblioteki), np: https://github.com/dagrejs/graphlib

Na twoich danych to będzie coś w stylu:

const Graph = require('@dagrejs/graphlib').Graph


const createPathsGraph = (edgesData) => {
  const paths = new Graph({ directed: false })
  edgesData.forEach(edge => paths.setEdge.apply(paths, edge))

  return paths
}


/* Przykłady */

const arr = [
  [5, 2, 430.1794455479025],
  [5, 4, 455.87184657079644],
  [4, 1, 503.85164417598463],
  [4, 3, 354.66577212546935],
  [3, 2, 229.77966449378414],
  [3, 1, 513.7192612106761],
  [2, 1, 349.2653565073386],
  [2, 0, 494.33272496892874],
  [1, 0, 223.40573843780768],
]

const paths = createPathsGraph(arr)

// Wszystkie powiązane punkty:
console.log(
  paths.neighbors(2) // [ '0', '1', '3', '5' ]
)

// Odległości między punktami:
console.log(
  paths.edge(2, 1), // 349.2653565073386
  paths.edge(2, 3)  // 229.77966449378414
)

 

PS
No ale "matematyka do programowania niepotrzebna" - więc kombinują ludzie jak koń pod górkę tworząc jakieś pokraczne, niewydajne potworki ;/

0 głosów
odpowiedź 8 stycznia 2018 przez kap Stary wyjadacz (11,620 p.)
edycja 8 stycznia 2018 przez kap
Dodatkowo policz sobie liczbę potencjalnych kombinacji dla swojej wersji (o ile dobrze patrzę, będą to kombinacje bez powtórzeń * 2 bo dublujesz dane):
https://codepen.io/anon/pen/YYYeMX?editors=0011

Jak widać złożoność "niezła" wyszła ;)

PS
Oczywiście rzeczywistych połączeń może być znacznie mniej - zależy jak wygląda logika ich tworzenia, w każdym razie rozwiązanie mocno ograniczone.

Podobne pytania

+1 głos
1 odpowiedź 418 wizyt
0 głosów
2 odpowiedzi 660 wizyt
0 głosów
0 odpowiedzi 138 wizyt
pytanie zadane 18 września 2020 w C i C++ przez RobcioXXL Użytkownik (710 p.)

92,536 zapytań

141,376 odpowiedzi

319,451 komentarzy

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

...