0

I have the following array:

var my_json = [{
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "845",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "1002",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD3",
  PRODUCT_QUANTITY_MT: "45",
}, {
  DATE: "2020-02-02",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "20",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "10",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "230",
}]

From the above array I want to create two new arrays, for each day for each product how much was sold. The final array should look like this.

The first value would be a default value call DATE followed by each product name.

var final = [{
  title: "DATE"
}, {
  title: "PROD1"
}, { 
  title: "PROD2"
}, {
  title: "PROD3"
}]

I managed to create this by doing the following

var columns = [{ "title":"DATE" }];

$.each(my_json, function(index, element) {                         
  columns.push({ "title": element.PRODUCT_NAME })
});

The second array should be in this format:

var data = [
  [ "2020-02-01", 845", "1002" , "45"],
  [ "2020-02-02", "20", "",  "" ],
  [ "2020-02-03", "10", "230",  "" ],
];

As you can see, on Feb 1 we have a value for all products sold but on Feb 2 it's only PROD1. Likewise on Feb 3 only PROD2 and PROD3.

Each row col should match the first array like bellow

enter image description here

desired output of two arrays as bellow

         var Array1 = [{title: "DATE"},{title: "PROD1"},{title: "PROD2"}, 
                      {title: "PROD3"}]

         var Array2 = [
                       [ "2020-02-01", 845", "1002" , "45"],
                       [ "2020-02-02", "20", "",  "" ],
                       [ "2020-02-03", "10", "230",  "" ],
                    ];
4
  • Could you give an example of the full desired output for your example Commented Feb 18, 2020 at 10:11
  • JSON is a data exchange format. Don't refer to native JavaScript arrays/objects as JSON, it's just confusing. Commented Feb 18, 2020 at 10:13
  • Just FYI nothing about this is JSON. You have an array of objects. I've edited the question as such Commented Feb 18, 2020 at 10:14
  • @Jacob add my desired output Commented Feb 18, 2020 at 10:16

4 Answers 4

1

Please refer below code

var my_json = [{
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "845",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "1002",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD3",
  PRODUCT_QUANTITY_MT: "45",
}, {
  DATE: "2020-02-02",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "20",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "10",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "230",
}];
var Array1 = [{
  title: "DATE"
}];
var Array2 = [];
for (var i = 0; i < my_json.length; i++) {
  add(Array1, my_json[i].PRODUCT_NAME);
  switch (my_json[i].PRODUCT_NAME) {
    case "PROD1":
      Array2.push([my_json[i].DATE, my_json[i].PRODUCT_QUANTITY_MT, "", ""])
      break;
    case "PROD2":
      Array2.push([my_json[i].DATE, "", my_json[i].PRODUCT_QUANTITY_MT, ""])
      break;
    case "PROD3":
      Array2.push([my_json[i].DATE, "", "", my_json[i].PRODUCT_QUANTITY_MT])
      break;
  }
}

function add(arr, name) {
  const {
    length
  } = arr;
  const id = length + 1;
  const found = arr.some(el => el.title === name);
  if (!found) arr.push({
    title: name
  });
  return arr;
}

for (var i = 0; i < Array2.length; i++) {
  if (i != Array2.length - 1 && Array2[i][0] == Array2[i + 1][0]) {    
    Array2[i + 1][1] != "" ? Array2[i][1] = Array2[i + 1][1] : Array2[i][1];   
    Array2[i + 1][2] != "" ? Array2[i][2] = Array2[i + 1][2] : Array2[i][2];    
    Array2[i + 1][3] != "" ? Array2[i][3] = Array2[i + 1][3] : Array2[i][3];
    Array2.splice(i + 1, 1);
    i--;
  }
}
console.log(Array1);

console.log(Array2);

Sign up to request clarification or add additional context in comments.

Comments

1

You could get an object with the indices for the columns and reduce the given data by looking up the right row and update the value for a certain column.

var data = [{ DATE: "2020-02-01", PRODUCT_NAME: "PROD1", PRODUCT_QUANTITY_MT: "845" }, { DATE: "2020-02-01", PRODUCT_NAME: "PROD2", PRODUCT_QUANTITY_MT: "1002" }, { DATE: "2020-02-01", PRODUCT_NAME: "PROD3", PRODUCT_QUANTITY_MT: "45" }, { DATE: "2020-02-02", PRODUCT_NAME: "PROD1", PRODUCT_QUANTITY_MT: "20" }, { DATE: "2020-02-03", PRODUCT_NAME: "PROD1", PRODUCT_QUANTITY_MT: "10" }, { DATE: "2020-02-03", PRODUCT_NAME: "PROD2", PRODUCT_QUANTITY_MT: "230" }],
    final = [{ title: "DATE" }, { title: "PROD1" }, { title: "PROD2" }, { title: "PROD3" }],
    cols = final.reduce((r, { title }, i) => (r[title] = i, r), {}),
    result = data.reduce((r, { DATE, PRODUCT_NAME, PRODUCT_QUANTITY_MT }) => {
        var row = r.find(q => q[0] === DATE);
        if (!row) r.push(row = Array.from({ length: final.length }, (_, i) => i ? '' : DATE));
        row[cols[PRODUCT_NAME]] = PRODUCT_QUANTITY_MT;
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

1

We can use reduce method:

let final = my_json.reduce((a, {DATE, PRODUCT_NAME, PRODUCT_QUANTITY_MT}) => {
  a['DATE'] = a['DATE'] || {title: 'DATE'};
  a[PRODUCT_NAME] = a[PRODUCT_NAME] || {title: PRODUCT_NAME};
  return a;
},{})

let prepareData = my_json.reduce((a, c) => {
  a[c.DATE] = a[c.DATE] || {date: c.DATE, values:[]};
  if (c.PRODUCT_QUANTITY_MT) {
    a[c.DATE].values.push(c.PRODUCT_QUANTITY_MT);
  }
  return a;
},{})

let maxArrayLength = 0;
const data = Object.entries(prepareData).reduce((a, [k, v], i)=> {
  if (maxArrayLength < v.values.length) {
      maxArrayLength = v.values.length;
  } else {
    let fillByQuotes = Array.from({ length: maxArrayLength - v.values.length }, (i) => '');
    v.values.push(...fillByQuotes);
  }

  a.push([k, ...v.values]);
  return a;
}, []);

An example:

let my_json = [{
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "845",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "1002",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD3",
  PRODUCT_QUANTITY_MT: "45",
}, {
  DATE: "2020-02-02",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "20",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "10",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "230",
}]


let final = my_json.reduce((a, {DATE, PRODUCT_NAME, PRODUCT_QUANTITY_MT}) => {
  a['DATE'] = a['DATE'] || {title: 'DATE'};
  a[PRODUCT_NAME] = a[PRODUCT_NAME] || {title: PRODUCT_NAME};
  return a;
},{})

let prepareData = my_json.reduce((a, c) => {
  a[c.DATE] = a[c.DATE] || {date: c.DATE, values:[]};
  if (c.PRODUCT_QUANTITY_MT) {
    a[c.DATE].values.push(c.PRODUCT_QUANTITY_MT);
  }
  return a;
},{})

let maxArrayLength = 0;
const data = Object.entries(prepareData).reduce((a, [k, v], i)=> {
  if (maxArrayLength < v.values.length) {
      maxArrayLength = v.values.length;
  } else {
    let fillByQuotes = Array.from({ length: maxArrayLength - v.values.length }, (i) => '');
    v.values.push(...fillByQuotes);
  }

  a.push([k, ...v.values]);
  return a;
}, []);

console.log(Object.values(final));
console.log(data);

Comments

1

Please check below code


function getDates (json) {
  var dates = [];

  json.forEach(ele => {
    if (!dates.includes(ele.DATE)) {
        dates.push(ele.DATE);
      }
  })

  return dates;
}


function getProducts (json) {
  let products = [];

  json.forEach(ele => {
    if (!products.includes(ele.PRODUCT_NAME)) {
        products.push(ele.PRODUCT_NAME);
      }
  })

  return products;
}

function getColumns (json) {
  let columns = [{ "title":"DATE" }];
  let dates = getDates(json);

  dates.forEach(date => {
    let column = { "title": date };
    columns.push(column);
  });

  return columns;
}

function getQuantityForDate(json, date) {
  let products = getProducts(json);
  let row = new Array(products.length + 1).fill("");
  row[0] = date;

  // Filter full data for a date
  let data = json.filter(ele => ele.DATE === date);

  // Filter product on particular date
  data.forEach(ele => {
    let product_index = products.indexOf(ele.PRODUCT_NAME);
    row[product_index + 1] = ele.PRODUCT_QUANTITY_MT;
  });

  return row;
}

function getFormattedData(json) {
    let grid_data = [];
    let dates = getDates(json);

    dates.forEach(date => {
      grid_data.push(getQuantityForDate(json, date));
    })

    return {
      "columns": getColumns(json),
      "data": grid_data
    }
}


let my_json = [{
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "845",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "1002",
}, {
  DATE: "2020-02-01",
  PRODUCT_NAME: "PROD3",
  PRODUCT_QUANTITY_MT: "45",
}, {
  DATE: "2020-02-02",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "20",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD1",
  PRODUCT_QUANTITY_MT: "10",
}, {
  DATE: "2020-02-03",
  PRODUCT_NAME: "PROD2",
  PRODUCT_QUANTITY_MT: "230",
}];

let grid_data = getFormattedData(my_json);
console.log(grid_data.columns)
console.log(grid_data.data)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.