I have following JSON data for Chart
var chartJson = [
{
header : '2016',
values : [1, 5, 9]
},
{
header : '2017',
values : [2, 4, 8]
},
{
header : '2018',
values : [3, 1, 5]
}
];
And needs to convert it into this format to feed my HTML table
var tableJson = [
{
2016 : 1,
2017 : 2,
2018 : 3
},
{
2016 : 5,
2017 : 4,
2018 : 1
},
{
2016 : 9,
2017 : 8,
2018 : 5
}
];
Any quick help will be appreciated to convert it into this format.
I tried using this code, but somehow missing on the logic.
let table = [];
for(var row of chartJson ){
for(var value of row.values)
{
table.push(
{
column : row.header,
value : value
});
}
}
var chartJson = [{
header: '2016',
values: [1, 5, 9]
},
{
header: '2017',
values: [2, 4, 8]
},
{
header: '2018',
values: [3, 1, 5]
}
];
let table = [];
chartJson.forEach((row, index) => {
row.values.forEach((val, j) => {
table[j] = { ...table[j],
[row.header]: val
}
});
});
console.log(table)
Iterate through every chartJson's element with its' values(through inner loop) till values' length and make an object from that.
Finally, push that object into the table array.
That's it.
Have a look at the snippet below:
var chartJson = [
{
header: '2016',
values: [1, 5, 9]
},
{
header: '2017',
values: [2, 4, 8]
},
{
header: '2018',
values: [3, 1, 5]
}
];
let table = [];
let len_of_chartJson = chartJson.length, len_of_values = chartJson[0].values.length;
for (var i = 0; i < len_of_chartJson; i++) {
let obj = {};
for (var j = 0; j < len_of_values; j++) {
obj[chartJson[j].header] = chartJson[j].values[i];
}
table.push(obj);
}
console.log(table);
let table = chartJson.reduce((tbl, rec) => {
rec.values.forEach((num, index) => {
if(!tbl[index]){
tbl[index] = {}
}
tbl[index][rec.header] = num
})
return tbl
}, [])
Array reduce function is used to loop through each object, than for each object it loop through each value, checking if the index exist in the table, if it does not exist, it create an empty object at current index. Finally it creates a key value in the current index object.
You read more about reduce function below
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
I have following array
let newArray = [
{
"conterTop": {
"uncategroized": [item1, item2, item3],
"categroized": [item4, item5]
}
},
{
"flooring": {
"uncategroized": [item1, item2, item3],
"categroized": [item4, item5]
}
}
]
I'm pushing countertop & flooring on runtime. Now I need to check if countertop already exists in newArray, it should not push countertop again. I have tried newArray.includes() but it's not working. Please any suggestion?
You can filter the array to look for your matching key and check the length of the filtered array. If the length is greater than 0, it exists. If not, it doesn't.
newArray.filter(x => return typeof(x.countertop) !== "undefined").length > 0
Here I just filtered out every value that doesn't have counterTop and check if any value left
let newArray = [{
"conterTop": {
"uncategroized": [1, 2, 3],
"categroized": [4, 5]
}
},
{
"flooring": {
"uncategroized": [1, 2, 3],
"categroized": [4, 5]
}
}
];
let isCounterTopExists = newArray.filter(x => x.conterTop).length > 0
console.log(isCounterTopExists);
This is what Array.prototype.some is for:
let newArray = [
{
"conterTop": {}
},
{
"flooring": {}
}
];
let testArray = [
{
"flooring": {}
}
];
const testArrayResult = testArray.some(obj => obj.conterTop);
const newArrayResult = newArray.some(obj => obj.conterTop);
console.log("testArray has 'conterTop':", testArrayResult);
console.log("newArray has 'conterTop':", newArrayResult);
how can i flatten an array without using flat(). by 1 level?
so far i have this
function flatten(array) {
let flattened = [];
for (let i = 0; i < array.length; i++) {
const current = array[i];
for (let j = 0; i < current.length; j++) {
flattened.push(current[j])
}
}
return flattened
}
console.log(flatten([['foo', 'bar'], ['baz', 'qux']]));
// -> ["foo", "bar", "baz", "qux"]
flatten([[1], [2], 3, 4, [5]]);
// -> [1, 2, 3, 4, 5]
flatten([false, [true, [false]], [true]]);
// -> [false, true, [false], true]
flatten([]);
// -> []
and its crashing my memory
I hope this helps
var twoDimension = [[1], [2], 3, 4, [5]];
var plano = twoDimension.reduce((acc, el) => acc.concat(el), []);
console.log(plano);
You could use Array.reduce and the spread syntax:
function flatten(array) {
return array.reduce(
(accumulator, item) => {
// if `item` is an `array`,
// use the `spread syntax` to
// append items of the array into
// the `accumulator` array
if (Array.isArray(item)) {
return [...accumulator, ...item];
}
// otherwise, return items in the
// accumulator plus the new item
return [...accumulator, item];
}
, []); // initial value of `accumulator`
}
console.log(flatten([['foo', 'bar'], ['baz', 'qux']]));
// -> ["foo", "bar", "baz", "qux"]
console.log(flatten([[1], [2], 3, 4, [5]]));
// -> [1, 2, 3, 4, 5]
console.log(flatten([false, [true, [false]], [true]]));
// -> [false, true, [false], true]
console.log(flatten([]));
// -> []
References:
Array.reduce - MDN
Spread syntax - MDN
To flatten by a single level only, Array#concat() can be leveraged. It accepts any amount of arguments, so an array can be spread into the function call:
[].concat(...arr)
This avoids any explicit loops. JavaScript handles everything:
function flatten(arr) {
return [].concat(...arr);
}
console.log(flatten([['foo', 'bar'], ['baz', 'qux']]));
// -> ["foo", "bar", "baz", "qux"]
console.log(flatten([[1], [2], 3, 4, [5]]));
// -> [1, 2, 3, 4, 5]
console.log(flatten([false, [true, [false]], [true]]));
// -> [false, true, [false], true]
console.log(flatten([]));
// -> []
You can use the following method if your array have primitive data type and want to flat it completely:
arr.toString().split(',');
you can use the reducer of javascript as an alternative to flat().
const arr = [1, 2, [3, 4]];
arr.reduce((acc, val) => acc.concat(val), []);
// [1, 2, 3, 4]
or you can use decomposition syntax
const flattened = arr => [].concat(...arr);
For more details, go to Mozilla MDN
You have an error here:
for (let j = 0; i < current.length; j++) {
// ^ wrong variable, should be j
And you need to check if the value is not an array, then just push the current value and continue the loop.
function flatten(array) {
let flattened = [];
for (let i = 0; i < array.length; i++) {
const current = array[i];
if (!Array.isArray(current)) {
flattened.push(current);
continue;
}
for (let j = 0; j < current.length; j++) {
flattened.push(current[j])
}
}
return flattened
}
console.log(flatten([['foo', 'bar'], ['baz', 'qux']]));
// -> ["foo", "bar", "baz", "qux"]
console.log(flatten([[1], [2], 3, 4, [5]]));
// -> [1, 2, 3, 4, 5]
console.log(flatten([false, [true, [false]], [true]]));
// -> [false, true, [false], true]
console.log(flatten([]));
// -> []
You had a typo where in your innermost loop you set i to 0 instead of j. The only other thing you needed to do was check to see if each element in the outer array was scalar (not an array) and push it to the returned array if so.
function flatten(arr) {
let flat = []
for (let i=0; i < arr.length; i++) {
const cur = arr[i]
if(!Array.isArray(cur)){
flat.push(cur)
}else{
for (let j=0; j < cur.length; j++) {
flat.push(cur[j])
}
}
}
return flat
}
console.log(flatten([['foo','bar'],['baz','qux']]))
console.log(flatten([[1],[2],3,4,[5]]))
console.log(flatten([false,[true,[false]],[true]]))
console.log(flatten([]))
Well you can use spread operator with reduce.
function flatten(array) {
return array.reduce((a,v) => [...a, ...(Array.isArray(v) ? v : [v])], []);
}
console.log(flatten([['foo', 'bar'], 'baz', 'qux']))
Following could be used as a general implementation of Array.prototype.flat()
function flattenArray(arr, depth = 1) {
if (!Array.isArray(arr)) {
return [arr];
}
return depth > 0
? arr.reduce(
(acc, curr) =>
acc.concat(
Array.isArray(curr) ? flattenArray(curr, depth - 1) : curr
),
[]
)
: arr.slice();
}
const a = [1, 2, 3, 4];
const b = "a";
const c = [1, [2, 3], 4];
const d = [1, [2, [3, 4], 5], 6];
const e = [1, [2, [3, [4, [5], [6]], 7], 8], 9];
console.log(flattenArray(a, Infinity));
console.log(flattenArray(b, Infinity));
console.log(flattenArray(c, Infinity));
console.log(flattenArray(d, Infinity));
console.log(flattenArray(e, Infinity));
There is another interesting way to do it.
Stringify the array
remove all array start symbol ([) and array end symbol(])
Add array start symbol at the beginning and array end symbol at the end.
Now parse the resulting string
const arr2 = [0, 1, 2, [5, [10, [3, 4]]]]
const arr2 = [0, 1, 2, [5, [10, [3, 4]]]]
console.log( JSON.parse('['+ JSON.stringify(arr2).replace(/\[/g, ' ').replace(/\]/g, ' ') + ']'))
Suppose given flatten number list without using the flat function is:
let array = [2,3,[5,2,[6,[3, [4, 5, [5, 1, 3]]]],1,1],9];
//let array= [2,3,[5,2,[6,[3, [4, 5, [5, {"key":"value"}, 3]]]],1,1],9];
//achieve above commented nested array condition using second approach.
The best answer already given by #Mahipal that would be first approach i.e.
array.toString().split(',')
with number array conversion
array.toString().split(',').map(n => +n)
another approach would be using function recursion without toString()
function flatter(arr) {
if (!Array.isArray(arr) && (!isNaN(arr) || typeof arr === "object")) {
return arr;
}
return arr.reduce((a, b) => {
a.push(...[].concat(flatter(b)));
return a;
}, [])
}
flatter(array);
and output is:
[ 2, 3, 5, 2, 6, 3, 4, 5, 5, 1, 3, 1, 1, 9 ]
Hope this would help many ones.
//Using Recursion
const arr = [1, 2, 3, 4, [5, 6, [6, 7], 7, 8]]
let arr2 = [];
function flat(arr) {
arr.forEach(element => {
if (typeof (element) == 'object') {
flat(element);
} else {
arr2.push(element);
}
});
}
flat(arr);
console.log(arr2);
var multiDimensionArray = [["a"],["b","c"],["d"]]; //array of arrays
var flatArray = Array.prototype.concat.apply([], multiDimensionArray); //flatten array of arrays
console.log(flatArray);
This worked for me:
function myFlattern(arr) {
let check;
do{
check=false;
for(let i=0;i<arr.length;i++)
{
if(Array.isArray(arr[i]))
{
check=true;
let x=arr[i];
arr.splice(i,1,...x);
}
}
}while(check)
return arr;
}
A possible alternative would be without using flat():
var arr = [['object1', 'object2'],['object1'],['object1','object2','object3']];
var flattened = [].concat.apply([],arr);
You can use this to forget about the depth of nesting:
let multiArr = [1, [1, 2, [3, 4]], [2, 4, [45, 98]]];
while (multiArr.find((elem) => Array.isArray(elem))) {
multiArr = [].concat.apply([], multiArr);
}
console.log(multiArr);
I have this array of numbers that i am working with that currently look this;
count = [1,4,3,1,2,3,4,5,6,2,3,5,7];
How can i transform and sort it to make it look like this;
count = [1,2,3,4,5,6,7,1,2,3,3,4,5];
Please help, any idea out there on how to approach this?
1) Get unique elements and sort
2) Get remaining elements and sort
3) combine (1) and (2) arrays.
count = [1, 4, 3, 1, 2, 3, 4, 5, 6, 2, 3, 5, 7];
const spSort = arr => {
const uniq = [...new Set([...arr])];
const rem = [];
const temp_set = new Set([...arr]);
arr.forEach(x => {
if (temp_set.has(x)) {
temp_set.delete(x);
} else {
rem.push(x);
}
});
return [...uniq.sort(), ...rem.sort()];
};
console.log(spSort(count));
Use a Set to create unique numbers and a hash object to keep count of duplicates:
const count = [1, 4, 3, 1, 2, 3, 4, 5, 6, 2, 3, 5, 7];
const hash = count.reduce((obj, num) => {
obj[num] = obj[num] ? ++obj[num] : 1;
return obj;
}, {});
const uniq = [...new Set(count)].sort();
uniq.forEach((num, _, arr) => {
while (--hash[num]) arr.push(num);
});
console.info(uniq);
I have objects like this one:
{
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
}
and I need to filter through dates object to check if there is specific date and return it's values (ex. if there is 7.01.2020). When I try fro ex user.dates, I get array with 3 different objects but when I use filteror map method, it doesn't work.
When user pick date I need to check if this date exists and add task to the existing ones and if it's new date, add date with tasks...
Any ideas? Thanks!
Actually you need to use for loop if it's not working with filter and map. I would suggest you to access date according to keys from the above arrays
let x = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
}
let y = Object.values(x.dates);
for(const [key,value] of Object.entries(y))
{
//getting particular date string
result = Object.keys(value);
console.log(result);
//converted date for result
date = new Date(result);
console.log(date);
}
please change include your required logic for return date.
I'd probably use a nested loop, where the inner loop is over the properties of the object:
let result = null;
outer: for (const entry of obj.dates) {
for (const [key, value] of Object.entries(entry)) {
if (key === target) {
result = value;
break outer;
}
}
}
Live Example:
const obj = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
};
const target = "7.01.2020";
let result = null;
outer: for (const entry of obj.dates) {
for (const [key, value] of Object.entries(entry)) {
if (key === target) {
result = value;
break outer;
}
}
}
console.log(result);
That makes at most one pass through the data, stopping as soon as it finds a match.
It can be a non-nested loop if you know that the objects in obj.dates only have a single property:
let result = null;
for (const entry of obj.dates) {
const [key] = Object.keys(entry);
if (key === target) {
result = value;
break;
}
}
Live Example:
const obj = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
};
const target = "7.01.2020";
let result = null;
for (const entry of obj.dates) {
const [key] = Object.keys(entry);
if (key === target) {
result = entry[key];
break;
}
}
console.log(result);
Another option would be to turn obj.dates into a Map and then use get on it:
const map = new Map(obj.dates
.map(entry => {
const [key] = Object.keys(entry);
return [key, entry[key]];
})
);
const result = map.get(target);
Live Example:
const obj = {
"name": "Ola",
"dates": [
{
"7.01.2020": [1, 2, 3]
},
{
"8.01.2020": [4, 5, 6]
},
{
"9.01.2020": [7, 8, 9]
}
],
"id": 7
};
const target = "7.01.2020";
const map = new Map(obj.dates
.map(entry => {
const [key] = Object.keys(entry);
return [key, entry[key]];
})
);
const result = map.get(target);
console.log(result);
That makes a full pass through the data, then a hashed (or similar) lookup on the resulting Map. It's useful if you need to look for multiple targets (since you just build the Map once). Note that this version assumes the objects in obj.dates only have one property.