简体   繁体   中英

How to store and format data properly in an array Javascript

I want to use the Charts.js Library and make the data displayed in the graph dependent on what a user has entered.

Right now I am not quite sure how to get the data in the right format so that I can use if for the library.

Currently I have a problem when combining the labels and values so that it matches the right index for the right label. I am having a table with two values ( A Month (Specified as Jan,Feb,Mar,Apr.etc.) and a numeric Value)

Now I need to combine months that appear twice and add the values associated with each month. I dont really know if I should use a 2d Array or 2 arrays for this. For example

var labels = ["Jan 17", "Jan 17", "Feb 17", "Mar 17", "Mar 17"];
var values = [10,10,25,40,100];

becomes

var newlabels = ["Jan 17", "Feb 17", "Mar 17"];
var newvalues = [20,25,140];

or as 2D Array:

var graphdata = [["Jan 17", 10],["Jan 17",10],["Feb 17",25],["Mar 17",40],["Mar 17",100]];

becomes

var newgraphData =[["Jan 17", 20],["Feb 17",25],["Mar 17",140]];

Either way is fine but I dont know which to use. Also I wouldn't quite know how to get the data in a 2d Array with jQuery selectors and the .map() function.

I was thinking of using the .map() and .reduce() function with a loop to go through each index but I cant quite seem to figure out how to do it.

Try this. You will get the formatted data in the arrays rLabels and rValues .

var labels = ["Jan 17", "Jan 17", "Feb 17", "Mar 17", "Mar 17"]
  , values = [10, 10, 25, 40, 100]
  , rLabels = []
  , rValues = [];
for (var i = 0; i < labels.length; i++) {
    var label = labels[i];
    var ind = rLabels.indexOf(label);
    if (ind == -1) {
        rLabels.push(label);
        rValues.push(values[i]);
    } else {
        rValues[ind] += values[i];
    }
}
const labels = ["Jan 17", "Jan 17", "Feb 17", "Mar 17", "Mar 17"];
const values = [10,10,25,40,100];

const result = labels.map((label, i) => ({label, value: values[i]}));
const grouped = []

result.forEach(o => {
  if (!this[o.label]) {
    this[o.label] = { label: o.label, value: 0 };
    grouped.push(this[o.label]);
  }
  this[o.label].value += o.value;
}, {});
console.log(grouped) // [ { label: 'Jan 17', value: 20 }, { label: 'Feb 17', value: 25 }, { label: 'Mar 17', value: 140 } ]

Here's another approach that aims to deconstruct the problem into smaller parts. Once we have a couple functions to transform data in a high-level way, assembling the final result becomes a trivial task.

We can start with a way to combine your two lists in a zipper -like fashion, using zip

const None =
  Symbol ()

const zip = ([ x = None, ...xs ], [ y = None, ...ys ]) =>
  x === None || y === None
    ? []
    : [ [ x, y ] ] .concat (zip (xs, ys))

const labels =
  [ "Jan 17", "Jan 17", "Feb 17", "Mar 17", "Mar 17" ]

const values =
  [ 10, 10, 25, 40, 100 ]

console.log (zip (labels, values))
// [ [ 'Jan 17', 10 ]
// , [ 'Jan 17', 10 ]
// , [ 'Feb 17', 25 ]
// , [ 'Mar 17', 40 ]
// , [ 'Mar 17', 100 ] 
// ]

With a list of [ key, value ] pairs, we can create a Map that groups values by key . Maps are lightning fast thanks to logarithmic search . JavaScript gives us Map, so when applicable, it's best to use it instead of a plain Object. At the very least, avoid using Array.prototype.indexOf like one answer suggests as it uses linear search and not suitable for larger data sets.

const group = (xs = []) =>
  xs.reduce ((acc, [ key, value ]) =>
    acc.has (key)
      ? acc.set (key, value + acc.get (key))
      : acc.set (key, value),
    new Map ())

console.log (group (zip (labels, values)))
// => Map { 'Jan 17' => 20, 'Feb 17' => 25, 'Mar 17' => 140 }

Lastly, we can convert from a Map to your desired output type using Array.from , Map.prototype.entries

const main = (labels = [], values = []) =>
  Array.from (group (zip (labels, values)) .entries ())

Here's a functioning example

 const None = Symbol () const zip = ([ x = None, ...xs ], [ y = None, ...ys ]) => x === None || y === None ? [] : [ [ x, y ] ] .concat (zip (xs, ys)) const group = (xs = []) => xs.reduce ((acc, [ key, value ]) => acc.has (key) ? acc.set (key, value + acc.get (key)) : acc.set (key, value), new Map ()) const main = (labels = [], values = []) => Array.from (group (zip (labels, values)) .entries ()) const labels = [ "Jan 17", "Jan 17", "Feb 17", "Mar 17", "Mar 17" ] const values = [ 10, 10, 25, 40, 100 ] console.log (main (labels, values)) // [ [ 'Jan 17', 20 ] // , [ 'Feb 17', 25 ] // , [ 'Mar 17', 140 ] // ] 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM