2017-10-26 85 views
11

Mam następującą tablicę:płaskim tablica do multi tablicy wymiarowe (JavaScript)

var sampleArray = [ 
    "CONTAINER", 
    "BODY", 
    "NEWS", 
    "TITLE"]; 

chcę mieć następujący wynik:

var desiredOutput = [{ 
     "CONTAINER": [{ 
      "BODY": [{ 
       "NEWS": [{ 
        "TITLE": [] 
       }] 
      }] 
     }] 
    }]; 

W jaki sposób można to osiągnąć w JavaScript?

Próbowałem już z pętlą rekurencyjną, ale to nie działa, daje mi niezdefiniowane.

dataChange(sampleArray); 
    function dataChange(data) { 
     for (var i = 0; i < data.length; i++) { 
      changeTheArray[data[i]] = data[i + 1]; 
      data.splice(i, 1); 
      dataChange(changeTheArray[data[i]]); 
     } 
    } 

Dzięki

Odpowiedz

3

to zrobi:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"]; 
 
const data = []; // Starting element. 
 
let current = data; // Pointer to the current element in the loop 
 

 
sampleArray.forEach(key => {  // For every entry, named `key` in `sampleArray`, 
 
    const next = [];    // New array 
 
    current.push({[key]: next}); // Add `{key: []}` to the current array, 
 
    current = next;    // Move the pointer to the array we just added. 
 
}); 
 

 
console.log(data);

{[key]: next} to stosunkowo nowa składnia. Są to: computed property names.

to:

const a = 'foo'; 
const b = {[a]: 'bar'}; 

jest podobny do:

const a = 'foo'; 
const b = {}; 
b[a] = 'bar'; 

Ty mógłby ponownego napisania forEach jako jedną wkładką:

const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"]; 
 
const data = []; // Starting element. 
 
let current = data; // Pointer to the current element in the loop 
 

 
sampleArray.forEach(key => current.push({[key]: current = [] })); 
 

 
console.log(data);

Ten current.push działa trochę wbrew intuicji:

  1. Construct nowy element do pchania. Przypisuje to nową wartość do current.
  2. Wciśnij nowy element do odwołanie.push został powołany na.
    • Odniesienie to jest wartość currentprzedcurrent = [].
+1

pytający to zmienne bestie ;-) – Alnitak

+0

Poszukałbym dodatkowej zmiennej tymczasowej, aby uniknąć dereferencji w drugiej linii twojej funkcji: 'let next = []; current.push ({[key]: next}); current = next' – Alnitak

+1

@Alnitak: Tak, byłem trochę zaskoczony. Dobra sugestia :-) – Cerbrus

1

Cześć Zrobiłem trochę demo:

var sampleArray = [ 
     "CONTAINER", 
     "BODY", 
     "NEWS", 
     "TITLE" 
    ], 
    generateArray = [], 
    tmp = null; 

for(var i = 0; i < sampleArray.length; i++) { 
    if(tmp===null){ 
    generateArray[sampleArray[i]] = {}; 
    tmp = generateArray[sampleArray[i]]; 
    }else{ 
    tmp[sampleArray[i]] = {}; 
    tmp = tmp[sampleArray[i]]; 
    }   
} 

console.log(generateArray); 
9

to robi to, co prosisz, w jednej linii, a bez dodatkowych zmiennych:

let desiredOutput = sampleArray.reduceRight((obj, key) => [ { [key]: obj } ], []); 

reduceRight wezwanie, począwszy od prawym końcu tablicy , stopniowo gromadzi bieżące dane (obsadzone wartością początkową []) jako wartość pojedynczego klucza w nowym obiekcie { [key] : _value_ }, gdzie ten obiekt sam jest pojedynczym wpisem w tablicy [ ... ].

+2

Fajne czary ... Próbowałem zbudować metodę "zredukować", ale nie mogłem jej uruchomić z powodu akumulatora przemieszczającego się po drzewie ... "Odwrócenie" to sprytny dotyk: D – Cerbrus

+0

@Xufox tak, Właśnie doszedłem do tego wniosku podczas komentowania - moje oryginalne testy wprawiły w zakłopotanie fakt, że '.reverse()' robi odwrócenie _w miejscu i moje dane testowe zostały już uszkodzone. Tak więc użycie '.reduceRight' jest w rzeczywistości lepsze, ponieważ pozostawia oryginalną tablicę nietkniętą. – Alnitak

+0

@Cerbrus faktycznie, 'reduceRight()' jest lepszy. – Alnitak