2017-11-14 9 views
0

Ich arbeite daran, einige JSON-Daten in ein Format zu konvertieren, das für die Darstellung einer Zeitreihe in C3 geeignet ist, die ein Array von Arrays als Spalteneingabe verwendet. Ich habe meine einzigartige X-Werte-Array, aber ich kann nicht einen guten Weg, um meine y-Werte zu bekommen. Sobald ich das fertig habe, muss ich y2 mit numSold hinzufügen, aber ich denke, wenn ich das lösen kann, werde ich in der Lage sein, diesen Teil herauszufinden.Bessere Möglichkeit, JSON in Arrays für die grafische Darstellung von Zeitreihen in C3 zu konvertieren?

Das ist das Endformat ich für die Daten benötigen:

[ 
    ["x", "9-2-17", "9-4-17", "10-2-17"], 
    ['item1-cost', 100, 150, 10], 
    ['item3-cost', 200, null, 20], 
    ... 
] 

Es gibt keine festgelegte Anzahl von Daten oder festgelegte Anzahl von Elementen. Es ist alles, was ich aus der Datenbank lese. Die Positionsnummern sind nicht unbedingt aufeinanderfolgend. Es ist uns nur wichtig, die Daten für Objekte grafisch darzustellen, für die wir Daten haben. Aber es gibt keine Daten für jede Datum-Element-Kombination. Wenn das passiert, muss ich eine Null einfügen, um anzuzeigen, dass das Element keine Daten für dieses Datum enthält. Artikelnummern sind 1-indiziert.

Mir geht es gut mit etwas von lo-Strich oder D3 zusätzlich zu den normalen JavaScript-Funktionen, um dies zu lösen, aber ich versuche, schwer zu lesen Code und ineffizienten Code zu vermeiden. Ich habe das Gefühl, dass andere dies brauchen müssen und dass es irgendeine Funktion geben muss, wie zum Beispiel eine Filterfunktion, die ich stattdessen benutzen sollte.

Meine aktuelle Implementierung ist nicht so effizient wie ich möchte und ist ein bisschen schwer zu lesen. Ich verwende die Artikelnummer als Index und mache ein spärliches Array, das ich später zusammenfassen muss. Hier ist die psudocode:

For every d object in data 
    For the i index of d.date in uniqueDates 
    If values[d.item] is undefined 
     Fill values[d.item]] with null for uniqueDates.length 
    Set values[d.item][i] to d.cost 
Convert values to dense format for graphing 

Hier ist ein Link auf die Fiddle Ich spiele mit:

https://jsfiddle.net/dbkidd/q3r3moqu/

var data = [ 
    {date: '9-2-17', item: 1, cost: 100}, 
    {date: '9-2-17', item: 3, cost: 200}, 
    {date: '9-4-17', item: 1, cost: 150}, 
    /* '9-4-17' does not have an entry for item 3 so cost should be counted as null */ 
    {date: '10-2-17', item: 1, cost: 10}, 
    {date: '10-2-17', item: 3, cost: 20} 
] 

var uniqueDates = _.uniq(_.flatMap(data, 'date')); 
uniqueDates.unshift('x'); 

var values = []; 
values.push(uniqueDates); 

function getLabel(index) { 
    return 'item' + index + '-' + 'cost'; 
} 

for (var d = 0; d < data.length; d++) { 
    var i = _.indexOf(uniqueDates, data[d].date); 
    if (data[d].item !== undefined) { 
    var item = data[d].item; 
    if (values[item] === undefined) { 
     values[item] = _.fill(Array(uniqueDates.length), null); 
     values[item][0] = getLabel(item); 
    } 
    values[item][i] = data[d].cost; 
    } 
} 

function checkIfUndefined(x) { 
    return (x !== undefined); 
} 

function sparseToDense(data) { 
    return data.filter(checkIfUndefined); 
} 

values = sparseToDense(values); 
+0

Beachten Sie, dass aus spärlichen Umwandlung ist zu dichten nicht unbedingt erforderlich; wir können einfach mit leeren Arrays füllen: https://stackoverflow.com/questions/47295727/how-to-use-sparse-arrays-with-c3-charts – Dallas

Antwort

1

ich dieses Problem war fasziniert und kam mit einer ersten Version auf. Es ist ein bisschen anders als deins, aber hier ist es. Ich werde feststellen, dass ich nicht versucht habe, die Daten zu sortieren oder die Artikel in etwas Nützliches umzubenennen, aber diese können hinzugefügt werden.

var data = [ 
 
\t {date: '9-2-17', item: 1, cost: 100}, 
 
    {date: '9-2-17', item: 3, cost: 200}, 
 
    {date: '9-4-17', item: 1, cost: 150}, 
 
    /* '9-4-17' does not have an entry for item 3 so cost should be counted as null */ 
 
    {date: '10-2-17', item: 1, cost: 10}, 
 
    {date: '10-2-17', item: 3, cost: 20}, 
 
    {date: '10-3-17', item: 2, cost: 2000} 
 
] 
 

 
// utility functions 
 
const product = (...sets) => 
 
    sets.reduce((acc, set) => 
 
    _.flatten(acc.map(x => set.map(y => [ ...x, y ]))), 
 
    [[]]); 
 

 
// the meat and potatoes 
 
const builder = lookup => pairs => pairs.reduce((agg, [item, date]) => { 
 
    const out = _.cloneDeep(agg); 
 
    const value = _.get(lookup, [date, item, 'cost'], null); 
 
    const evalue = _.get(out, date, []); 
 
    evalue.push(value); 
 
    _.set(out, date, evalue); 
 
    return out; 
 
}, {}) 
 

 
// setup data structures for searching 
 
const byDateByItem = _.mapValues(_.groupBy(data, 'date'), x => _.keyBy(x, 'item'));  
 
const items = _.uniq(data.map(x=>x.item)); 
 
const dates = _.uniq(data.map(x=>x.date)); 
 

 
// create all posibilities 
 
const pairs = product(items, dates); 
 
// populate possibilities with values 
 
const hash = builder(byDateByItem)(pairs); 
 
// put keys with values in their respective lists 
 
const p = _.toPairs(hash).map(_.flatten); 
 
// smash data into a matrix type thing 
 
const table = [['x',...items], ...p]; 
 
// flip the table on it's side (╯°□°)╯︵ ┻━┻ 
 
const out = _.zip(...table); 
 
console.log('out', out);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

+0

Hey, das ist ziemlich cool. Ich frage mich, wie es in der Leistung für viele Daten halten würde. – Dallas

+0

Erste jsperf.com Ergebnisse haben meine ursprüngliche Implementierung als schneller, aber ich bin mir nicht sicher, ob das stimmt, wenn die Arrays riesig sind. – Dallas

+1

Ich wette, es ist nicht blitzschnell, aber mehr als wahrscheinlich würden Sie JS nicht verwenden, wenn Sie blitzschnell perf. Wollen. Die meiste Zeit werden Sie in der Lage sein, andere Dinge zu ändern, bevor Sie Mikro-Optimierungen für den Code vornehmen müssen. – ktilcu

Verwandte Themen