Javascript - konvertieren verschachtelten Arrays in Objekt von Arrays

stimmen
1

Ich habe eine verschachtelte Array mit unbekannter Form. Hier ist ein Beispiel:

[head,val1,val2,val3,
    [head2,val4,val5,
        [head3,val6,val7, 
            [head4, val8],val9]],
    [head5, val10, val11]
]

Die Arrays weisen alle eine Länge von 2 oder größer ist. Ein Array kann eine beliebige Anzahl von anderen Anordnungen enthalten, die auch eine beliebige Anzahl von Feldern enthalten kann. Alle Werte sind entweder Strings oder Arrays.

Ich versuche, diese zu einem einzigen Objekt mit der folgenden Form zu konvertieren:

{head: [val1,val2,val3, 
    {head2: [val4,val5, 
        {head3: [val6,val7, 
            {head4: [val8]}, val9]},
    {head5: [val10, val11]}
]}

Grundsätzlich muss jedes Array auf ein Objekt umgewandelt werden , in dem der erste Wert der Schlüssel und der Rest der Anordnung ist der Wert ist . Ich habe versucht mit reduce, kann aber durchaus nicht richtig.

Veröffentlicht am 07/11/2018 um 23:44
quelle vom benutzer
In anderen Sprachen...                            


6 antworten

stimmen
4

In diesem Fall wissen Sie nicht, wie tief verschachtelten Arrays sind, so ist es eine gute Idee, eine rekursive Funktion zu entwerfen.

Im Basisfall Ihrer rekursive Funktion ist die Eingabe nicht ein Array, so dass nur die Eingabe zurück.

In dem Fall, wenn die Eingabe ein Array ist, erstellen Sie eine JS-Objekt mit einer einzigen Eigenschaft, deren Name auf das erste Element in dem Eingangsfeld gleich ist, und deren Wert gleich dem Rest des Feldes ... Sie müssen rekursiv aufrufen Ihre Funktion gegen jeden der verbleibenden Mitglieder ihren Wert in der resultierenden Array zu erhalten.

var a = ["head","val1","val2","val3",
    ["head2","val4","val5",
        ["head3","val6","val7", 
            ["head4", "val8"],"val9"]],
    ["head5", "val10", "val11"]
];

function convert(val) {
  var result;
  if (Array.isArray(val)) {
    var key = val[0];
    var vals = val.slice(1);
    result = {};
    result[key] = [];
    for (var i = 0; i < vals.length; i++) {
      result[key].push(convert(vals[i]));
    }
  } else {
    result = val;
  }
  return result;
}

console.log(convert(a));

Beantwortet am 08/11/2018 um 00:00
quelle vom benutzer

stimmen
2

Etwas wie das?

function convert(arr) {
  if (arr instanceof Array) {
    const [key, ...values] = arr;
    return { [key]: values.map(convert) };
  } else {
    return arr;
  }
}

const test = ["head","val1","val2","val3",
    ["head2","val4","val5",
        ["head3","val6","val7", 
            ["head4", "val8"],"val9"]],
    ["head5", "val10", "val11"]
];

console.log(convert(test));

Beantwortet am 08/11/2018 um 00:13
quelle vom benutzer

stimmen
2

Tun Sie es einfach rekursiv wie folgt:

function convert(arr) {
  return {
    [arr[0]]: arr.slice(1).map(item => Array.isArray(item)? convert(item): item)
  }
}

Die Funktion convertgibt ein Objekt ein Schlüsselwertpaar containg. Der Schlüssel ist , arr[0]und der Wert ist , der Rest der Elemente in dem Array ( arr.slice(1)) abgebildet in ein neues Array , so dass convertauf allen Array - Elementen innerhalb dieses Array genannt wird.

ES5 Version:

function convert(arr) {
  var obj = {};
  obj[arr[0]] = arr.slice(1).map(function(item) {
      return item instanceof Array? convert(item): item;
  });
  return obj;
}

Beispiel:

function convert(arr) {
  return {
    [arr[0]]: arr.slice(1).map(item => Array.isArray(item)? convert(item): item)
  }
}

let arr = ["head","val1","val2","val3",
    ["head2","val4","val5",
        ["head3","val6","val7", 
            ["head4", "val8"],"val9"]],
    ["head5", "val10", "val11"]
];

let result = convert(arr);

console.log(result);

Beantwortet am 08/11/2018 um 00:05
quelle vom benutzer

stimmen
1

Da Sie mit dem Stichwort dies lodashhier ist eine kurze Lösung mit ihm auch:

var data = ["head","val1","val2","val3", ["head2","val4","val5", ["head3","val6","val7", ["head4", "val8"],"val9"]], ["head5", "val10", "val11"] ]

const f = (d) => ({[_.head(d)]: _.map(_.tail(d), x => _.isArray(x) ? f(x) : x)})

console.log(f(data))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Es ist eine Lösung , die rekursive lodash nutzt .head zu erhalten das erste Element des Arrays,.tail für alleaber die ersten und dann_.mapjedes der Elemente zu gehen und einen Array zurück.

Beantwortet am 08/11/2018 um 02:34
quelle vom benutzer

stimmen
1

Dieser effiziente Ansatz vermeidet mit slice()(was eine temporäre Array der Größe N-1 erzeugen würde , die gelöscht werden):

function change(a) {
  let b = [];
  for (let i = 1; i < a.length; i++) {
    let v = a[i];
    b.push(Array.isArray(v) ? change(v) : v);
  }
  return {[a[0]]: b};
}

console.log(change(
  ["head","val1","val2","val3",
    ["head2","val4","val5",
        ["head3","val6","val7", 
            ["head4", "val8"],"val9"]],
    ["head5", "val10", "val11"]
  ]
));

Beantwortet am 08/11/2018 um 01:50
quelle vom benutzer

stimmen
1

ES6: Sie können so etwas wie die folgenden tun

function convertArrayToObject(arr) {
  return Array.isArray(arr) && arr.length ? {
    [arr[0]]: arr.slice(1).map(convertArrayToObject)
  } : arr;
}

Dieser Code definiert eine Funktion , convertArrayToObjectdie das Element selbst zurückkehrt , wenn es nicht ein Array ist , oder legt das erste Element als Schlüssel und ruft die Funktion , wenn sie mit den übrigen Elementen , wie die Werte , wenn es sich um ein Array ist.

Beantwortet am 08/11/2018 um 00:13
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more