• 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

+1 głos
250 wizyt
pytanie zadane 7 stycznia 2018 w JavaScript przez Janusz92 Bywalec (2,130 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,700 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 (187,720 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 (229,500 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 (187,720 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,700 p.)

@Krzycho92, Nazwy zmiennych miodzio :P

komentarz 8 stycznia 2018 przez ScriptyChris Mędrzec (187,720 p.)
Myślę, że jak na przykładowy kod, nazwy zmiennych są dosyć czytelne.
komentarz 8 stycznia 2018 przez kap Stary wyjadacz (11,700 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 (187,720 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,700 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 (187,720 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,700 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,700 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,700 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ź 118 wizyt
0 głosów
2 odpowiedzi 272 wizyt
0 głosów
0 odpowiedzi 102 wizyt
pytanie zadane 18 września 2020 w C i C++ przez RobcioXXL Użytkownik (710 p.)

89,693 zapytań

138,297 odpowiedzi

309,243 komentarzy

59,623 pasjonatów

Motyw:

Akcja Pajacyk

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

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...