0

I need to create an array of array. It is worth noting that the database is very large and that if any attribute does not have a corresponding value, it sends an empty string. I've tried with map and reduce but I wasn't successful:

Any help will be appreciated.

Below I show an example of the expected output:

outputExpected = [
  ["id", 1, 2],
  ["name", "name1", "name2"],
  ["price", 6.95, 998.95],
  ["promoPrice", 5.91, 333.91],
  ["category", "test1 | test2", "test3 | test4"],
]

Any way to solve this problem performatically?

this is my code:

let arrayObj = [{
    "id": 1,
    "name": "name1",
    "price": 6.95,
    "promoPrice": 5.91,
    "category": ["test1, test2"]
  },
  {
    "id": 2,
    "name": "name2",
    "price": 998.95,
    "promoPrice": 333.91,
    "category": ["test3, test4"]
  }
]

const headers = ["id", "name", "price", "promoPrice", "category"]
const result1 = headers.concat(arrayObj.map((obj) => {
  return headers.reduce((arr, key) => {
    arr.push(obj[key]) return arr;
  }, [])
}))

console.log(result1)

3
  • 2
    Show what you tried, then we'll show how to fix it. We won't write it for you. Commented Dec 17, 2021 at 18:30
  • this is my code: const headers = ["id","name","price","promoPrice", "category"] const result1 = headers.concat(arrayObj.map((obj) => { return headers.reduce((arr, key) => { arr.push(obj[key]) return arr; }, []) })) Commented Dec 17, 2021 at 18:32
  • add your code in the question. use edit Commented Dec 17, 2021 at 18:32

4 Answers 4

3

Reduce the array to a Map. On each iteration convert the object to an array of [key, value] pairs using Object.entries(). Use Array.forEach() to iterate the entries and add them to the map. Convert the Map's values iterator to an array using Array.from():

const arr = [{"id":1,"name":"name1","price":6.95,"promoPrice":5.91,"category":["test1", "test2"]},{"id":2,"name":"name2","price":998.95,"promoPrice":333.91,"category":["test3", "test4"]}]

const result = Array.from(arr.reduce((acc, o) => {
  Object.entries(o)
    .forEach(([k, v]) => {
      if(!acc.has(k)) acc.set(k, [k])
      
      acc.get(k).push(Array.isArray(v) ? v.join(' | ') : v)
    })
  
  return acc
}, new Map()).values())

console.log(result)

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

4 Comments

in the same approach, how can i consider the new attribute in expected output? I want to concatenate the strings "name[i]: values[i]". I'm stuck in this step.Tks again!
Please open a new question
I edited this one. Is enough?
That question is done. Restore it to it's previous state, and open a new question.
2

You could simply map the value and check if an item is an array, then take the joined values or the value itself.

const
    data = [{ id: 1, name: "name1", price: 6.95, promoPrice: 5.91, category: ["test1, test2"] }, { id: 2, name: "name2", price: 998.95, promoPrice: 333.91, category: ["test3, test4"] }],
    headers = ["id", "name", "price", "promoPrice", "category"],
    result = data
        .reduce(
            (r, o) => headers.map((k, i) => [
                ...r[i],
                Array.isArray(o[k]) ? o[k].join(' | ') : o[k]
            ]),
            headers.map(k => [k]),
        );

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

Comments

1

construct one init array with all possible keys with the wanted order, then uses Array.reduce and Array.forEach to Array.push value for per key based on its index.

const arrayObj = [
  {
  "id":1,
  "name":"name1",
  "price":6.95,
  "promoPrice":5.91,
  "category":["test1", "test2"]
  },
  {
    "id":2,
    "name":"name2",
    "price":998.95,
    "promoPrice":333.91,
    "category":["test3", "test4"]
  }
]

function ConvertToArray2D (items) {
  let init = [['id'], ['name'], ['price'], ['promoPrice'], ['category']]
  if (!items) return init
  return arrayObj.reduce((pre, cur) => {
    init.forEach((key, index) => {
      pre[index].push(Array.isArray(cur[key[0]]) ? cur[key[0]].join('|') : cur[key[0]])
    })
    return pre
  }, init.slice())
}
console.log(ConvertToArray2D(arrayObj))

Comments

0

This can be handled with a standard 'zip' after mapping your objects to arrays of values in line with the headers array. (This also allows for the result to be pivoted back).

//** @see https://stackoverflow.com/a/10284006/13762301
const zip = (...rs) => [...rs[0]].map((_, c) => rs.map((r) => r[c]));

const headers = ['id', 'name', 'price', 'promoPrice', 'category'];
const arrayObj = [{ id: 1, name: 'name1', price: 6.95, promoPrice: 5.91, category: ['test1', 'test2'] },{ id: 2, name: 'name2', price: 998.95, promoPrice: 333.91, category: ['test3', 'test4'] },];

const result = zip(
  headers,
  ...arrayObj.map((o) => headers.map(h => Array.isArray(o[h]) ? o[h].join(' | ') : o[h]))
);

console.log(result);

// which also allows it to be reversed
console.log(zip(...result));
.as-console-wrapper { max-height: 100% !important; top: 0; }

see: Javascript equivalent of Python's zip function for further zip discussion.

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.