2016-07-27 15 views
-1

I einen JavaScript-Array ändern möge, so dass die Elemente die gleichen Werte für Spezifizieren Eigenschaften verschmelzen zu einem Objekt in einer Art und Weise aufweisen, dass die anderen Eigenschaften als kommagetrennte Zeichenfolge gehalten werden, , JSON-Zeichenfolge oder ein Array. Grundsätzlich möchte ich dies drehen:Javascript - Reduzieren Array mit mehreren Schlüsselobjekten

[ 
    { 
     "language" : "english", 
     "type" : "a", 
     "value" : "value1" 
    }, 
    { 
     "language" : "english", 
     "type" : "a", 
     "value" : "value2" 
    }, 
    { 
     "language" : "english", 
     "type" : "b", 
     "value" : "value3" 
    }, 
    { 
     "language" : "spanish", 
     "type" : "a", 
     "value" : "valor1" 
    } 
] 

in diese:

[ 
    { 
     "language" : "english", 
     "type" : "a", 
     "value" : ["value1" , "value2"] // A Json string is welcome too 
    }, 
    { 
     "language" : "english", 
     "type" : "b", 
     "value" : "value3" 
    }, 
    { 
     "language" : "spanish", 
     "type" : "a", 
     "value" : "valor1" 
    } 
] 

ich versucht habe, Iterieren und Filterung, dann upserted das Objekt wie im Snippet gegeben. Aber ich frage mich, ob es eine elegantere Art und Weise gibt, das zu tun.

P. S EcmaScript6 und zusätzliche JS-Bibliothek Vorschläge sind willkommen.

var originalArray = [ 
 
\t { 
 
\t \t "language" : "english", 
 
\t \t "type" : "a", 
 
\t \t "value" : "value1" 
 
\t }, 
 
\t { 
 
\t \t "language" : "english", 
 
\t \t "type" : "a", 
 
\t \t "value" : "value2" 
 
\t }, 
 
\t { 
 
\t \t "language" : "english", 
 
\t \t "type" : "b", 
 
\t \t "value" : "value3" 
 
\t }, \t 
 
\t { 
 
\t \t "language" : "spanish", 
 
\t \t "type" : "a", 
 
\t \t "value" : "valor1" 
 
\t } 
 
]; 
 

 
var resultingArray = []; 
 

 
// iterate through the original array 
 
$.each(originalArray, function(i, val) { 
 
    // apply filter on key properties (i.e. language and type) 
 
    var result = resultingArray.filter(function(obj) { 
 
    return (obj.language === val.language && obj.type === val.type); 
 
    }); 
 
    // if a record exists, update its value 
 
    if (result.length === 1) { 
 
    result[0].value += (", " + val.value); 
 
    } 
 
    // else, add value 
 
    else if (result.length === 0) { 
 
    resultingArray.push(val); 
 
    } 
 
    // if multiple rows exist with same key property values... 
 
    else { 
 
    alert("Too many records with language '" + val.language + "' and type '" + val.type + "'"); 
 
    } 
 
}); 
 

 
console.log(JSON.stringify(resultingArray));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

+1

[Hier ist meine vorgeschlagene Lösung war] (http://pastebin.com/bx66Vc5K), je nachdem, was Sie "elegant" betrachten. Das Problem mit Ihrem Code ist, dass er in 'O (N^2)' ausgeführt wird, da die Funktion 'filter' einmal bei der ersten Iteration von' each', zweimal bei der zweiten Iteration und so weiter ausgeführt wird. Das ist nicht nötig. –

+1

Und [hier] (https://jsfiddle.net/Arnauld/0eyxbf70/) gehörte mir, wobei "Wert" immer ein Array ist. BTW: Ich denke, deine 'alert()' Anweisung kann nie ausgelöst werden. Wenn Sie nicht den gleichen _value_ für den gleichen Schlüssel (Sprache + Typ) möchten, müssen Sie es anders machen. – Arnauld

+0

hey, Ihr JS verwendet jQuery, warum fügen Sie kein jQuery-Tag hinzu? Ich war lernen und stellen Sie sicher, mit reinem Javascript 'forEach' um Ihnen zu helfen -_-! –

Antwort

0

Dies ist, was Sie brauchen?

var baseData= [ 
 
    { 
 
     "language" : "english", 
 
     "type" : "a", 
 
     "value" : "value1" 
 
    }, 
 
    { 
 
     "language" : "english", 
 
     "type" : "a", 
 
     "value" : "value2" 
 
    }, 
 
    { 
 
     "language" : "english", 
 
     "type" : "b", 
 
     "value" : "value3" 
 
    }, 
 
    { 
 
     "language" : "spanish", 
 
     "type" : "a", 
 
     "value" : "valor1" 
 
    } 
 
]; 
 

 
var newData = []; 
 
baseData.forEach(function(item, index) { 
 
    if (newData.length === 0) { 
 
    newData.push(item); 
 
    
 
    } else { 
 
    var dIndex = -1; 
 
    newData.forEach(function(itm, idx) { 
 
     if (item.language === itm.language && item.type === itm.type) dIndex = idx; 
 
    }); 
 
    
 
    if (dIndex !== -1) { 
 
     var oldValue = newData[dIndex].value; 
 
     
 
     if (typeof(oldValue).toString() === 'string') { 
 
     newData[dIndex].value = [oldValue, item.value]; 
 
     } 
 
    } else { 
 
     newData.push(item); 
 
    } 
 
    } 
 
}); 
 
console.log(newData);