Add text before array elements - javascript

I'm currently working on a data visualisation with d3.js where I have GDP data data for each quarter of a year. The data looks like this:
[
[
"1947-01-01",
243.1
],
[
"1947-04-01",
246.3
],
[
"1947-07-01",
250.1
]
]
What I want is turn it into the following:
[
[
date: "1947-01-01",
GDP: 243.1
],
[
date: "1947-04-01",
GDP: 246.3
],
[
date: "1947-07-01",
GDP: 250.1
]
I tried doing it like this but it turns the array elements into strings.
d3.json("data/GDP-data.json").then(function (dataTotal) {
data = dataTotal.data;
console.log(data);
for(var i=0;i<data.length;i++){
data[i]["0"] = new Date(data[i]["0"])
data[i]["0"]="date: "+data[i]["0"];
data[i][1] = "GDP: "+data[i][1];
}
}
Is there a way to not turn each element into a string while still adding text before it? It would make it a lot easier to call certain data points.

Use map
arr.map( s => ({ date : s[0], gdp : s[1] }) );
Demo
var arr = [
[
"1947-01-01",
243.1
],
[
"1947-04-01",
246.3
],
[
"1947-07-01",
250.1
]
];
var output = arr.map(s => ({
date: s[0],
gdp: s[1]
}));
console.log(output);

You can use map to achieve that
var data = [
[
"1947-01-01",
243.1
],
[
"1947-04-01",
246.3
],
[
"1947-07-01",
250.1
]
];
var r = data.map(o=> ({date: o[0], GDP: o[1]}));
console.log(r)

Related

Split array elements dynamically

I have below scenarios to handle.
let data = [
[ "ALISHA", "SUICA", "PASMO" ],
[ "HARMONY" ],
[ "OCTOPUS" ]
]
let data1 = [
[ "ALISHA", ],
[ "HARMONY" ],
[ "OCTOPUS", "SUICA", "PASMO" ]
]
For both of the above data, i want the result to look like this.
let result = [
[ "ALISHA" ],
[ "HARMONY" ],
[ "OCTOPUS" ],
[ "SUICA" ],
[ "PASMO" ]
]
Can someone please let me know how to achieve this. I tried the following but no success
let result = []
for (let i = 0; i < data.length; i++) {
let split = data[i].split(","); // just split once
result.push(split[0]); // before the comma
}
we will use forEach method on main array inside forEach we will use if condition if is array and length more than 1 will add another forEach method and push sub array to main array after that remove sub array
look like that
let data = [
["ALISHA"],
["HARMONY"],
["OCTOPUS", "SUICA", "PASMO"]
]
data.forEach((cur, index) => {
if (Array.isArray(cur) && cur.length > 1) {
cur.forEach(cur => data.push([cur]))
data.splice(index, 1);
}
})
console.log(data)
Uses Array.reduce extract all elements, then convert to [string] by Array.map.
const data = [
[ "ALISHA" ],
[ "HARMONY" ],
[ "OCTOPUS", "SUICA", "PASMO" ]
]
console.log(
data.reduce((pre, cur) => [...pre, ...cur], []).map(item => [item])
// data.reduce((pre, cur) => pre.concat(...cur), []).map(item => [item]) // different methods but same logic (uses Array.concat instead of spread operator)
)
You can use flat and map
const data = [["ALISHA"], ["HARMONY"], ["OCTOPUS", "SUICA", "PASMO"]];
const result = data.flat().map((a) => [a]);
console.log(result);

Javascript: update a column in matrix

I want to update an entire column of a matrix.
I started by initializing the matrix like:
m =({length:10}, (_,i) => Array.from({length:2}, (_,j) => i+'x'+j));
Then, I have an array of 2 element (say, a2) that I want to put in the j-th column of the matrix with manipulation.
If I am using matlab I would do the following: m(:,j)=a2+ m(:,j)
How can I do this in javascript?
Do you mean like this?:
const m = Array.from({length:10}, (_,i) => Array.from({length:2}, (_,j) => i+'x'+j));
console.log("before", m);
const j = 2;
const a2 = "z"
const n = m.map(row => {row.splice(j, 0, a2); return row});
console.log("after", n);
before manipulation:
before [
[ "0x0", "0x1" ],
[ "1x0", "1x1" ],
[ "2x0", "2x1" ],
[ "3x0", "3x1" ],
[ "4x0", "4x1" ],
[ "5x0", "5x1" ],
[ "6x0", "6x1" ],
[ "7x0", "7x1" ],
[ "8x0", "8x1" ],
[ "9x0", "9x1" ]
]
And after manipulation (i.e. add "z" to column 2):
after [
[ "0x0", "0x1", "z" ],
[ "1x0", "1x1", "z" ],
[ "2x0", "2x1", "z" ],
[ "3x0", "3x1", "z" ],
[ "4x0", "4x1", "z" ],
[ "5x0", "5x1", "z" ],
[ "6x0", "6x1", "z" ],
[ "7x0", "7x1", "z" ],
[ "8x0", "8x1", "z" ],
[ "9x0", "9x1", "z" ]
]
Or if a2 should be an array itself? Then, the simple case that it is a 1D array:
const m = Array.from({length:10}, (_,i) => Array.from({length:2}, (_,j) => i+'x'+j));
console.log("before", m);
const j = 2;
const a2 = Array.from({length:10}, (_,j) => 'z'+j)
const n = m.map((row, i) => {row.splice(j, 0, a2[i]); return row});
console.log("after", n);
After manipulation (i.e. add "z{ i }" to column 2):
after [
[ "0x0", "0x1", "z0" ],
[ "1x0", "1x1", "z1" ],
[ "2x0", "2x1", "z2" ],
[ "3x0", "3x1", "z3" ],
[ "4x0", "4x1", "z4" ],
[ "5x0", "5x1", "z5" ],
[ "6x0", "6x1", "z6" ],
[ "7x0", "7x1", "z7" ],
[ "8x0", "8x1", "z8" ],
[ "9x0", "9x1", "z9" ]
]
Or the more complex case when a2 is a 2D array:
const m = Array.from({length:10}, (_,i) => Array.from({length:2}, (_,j) => i+'x'+j));
console.log("before", m);
const j = 2;
const a2 = Array.from({length:10}, (_,i) => Array.from({length:2}, (_,j) => i+'z'+j));
const n = m.map((row, i) => {row.splice(j, 0, a2[i]); return row.flat()});
console.log("after", n);
After manipulation (i.e. add "z{ i }" to column 2):
after [
[ "0x0", "0x1", "0z0", "0z1" ],
[ "1x0", "1x1", "1z0", "1z1" ],
[ "2x0", "2x1", "2z0", "2z1" ],
[ "3x0", "3x1", "3z0", "3z1" ],
[ "4x0", "4x1", "4z0", "4z1" ],
[ "5x0", "5x1", "5z0", "5z1" ],
[ "6x0", "6x1", "6z0", "6z1" ],
[ "7x0", "7x1", "7z0", "7z1" ],
[ "8x0", "8x1", "8z0", "8z1" ],
[ "9x0", "9x1", "9z0", "9z1" ]
]
I think using Array.prototype.forEach and Array.prototype.splice is a good way to accomplish this:
// Setup for demo
const Row = (w) =>Array.from({length:w}).fill('').map((c,i)=>c=i);
const Matrix = (h, w) => Array.from({length:h}).fill('').map(r=>r=Row(w));
const print = (mtx) => mtx.forEach(r=>console.log([...r].join(", ")));
// Original state of matrix
const m1 = Matrix(2,10);
print(m1);
console.log('----------');
// Insertion function
const insertCol = (mtx, cInd, newCol) => {
mtx.forEach( (row, rInd) => { row.splice(cInd, 0, newCol[rInd]); }
);
}
// Matrix with inserted column
const someCol = ['X','Y'];
insertCol(m1, 3, someCol);
print(m1);

How to match the string values of 2 arrays when the other array has a Number(value)

I'm new to Javascript. I'm trying to get the Math.max(...arr1[i][1]) of the array(arr1), only when it is matched with the 2nd array(arr2). Then, push it on the array(arr3) and the result should have no duplicate values.
I tried iterating both arrays(arr1 & arr2) then used an "if statement" for matching them.
var arr1 = [ [ 'abandon', -2 ],
[ 'abandon', 1 ],
[ 'abandon', -2 ],
[ 'abduct', 1 ],
[ 'abduct', -2 ],
[ 'abduct', -2 ],
[ 'abhor', -3 ],
[ 'abhor', 1 ],
[ 'abhor', -1 ],
[ 'abil', 2 ],
[ 'abil', 4 ] ];
var arr2 = [ [ 'abandon' ],
[ 'abil' ],
[ 'abhor' ],
[ 'abduct' ],
['test'],
['hey'],
['testAgain'],
['array']];
var arr3 = [];
const mapping = arr2.map(word => {
return word
})
for(var i = 0; i < arr1.length; i++){
if(arr1[i][0] === mapping){
arr3.push(Math.max(...arr1[i][1]))
}
}
let arr4 = [...new Set(arr3)]
//example result:
var arr4 = [[abandon, -2],
[abduct, -2],
[abhor, -3],
[abil, 4]... and so on]
I know I'm doing something wrong, and I'm out of option. Need help.
You can better use a Set instead of an array like arr2 directly for finding a match as it will be constant time lookup in case of a Set.
Then use a Array.prototype.filter to filter the array arr1 and get those arrays which are in arr2.
Lastly Array.prototype.reduce would help you make an object with the keys being the words and values being the largest value for that word in the arr1 and you could use Object.entries from that object returned from reduce to get the data in the form of a 2-D array:
var arr1 = [ [ 'abandon', -2 ],
[ 'abandon', 1 ],
[ 'abandon', -2 ],
[ 'abduct', 1 ],
[ 'abduct', -2 ],
[ 'abduct', -2 ],
[ 'abhor', -3 ],
[ 'abhor', 1 ],
[ 'abhor', -1 ],
[ 'abil', 2 ],
[ 'abil', 4 ] ];
var arr2 = [ [ 'abandon' ],
[ 'abil' ],
[ 'abhor' ],
[ 'abduct' ],
['test'],
['hey'],
['testAgain'],
['array']];
var lookup = new Set(arr2.flat());
var mapping = arr1.filter(([word, val]) => lookup.has(word));
var data = Object.entries(mapping.reduce((acc, o, i) => {
if(acc[o[0]]){
acc[o[0]] = Math.max(o[1], acc[o[0]]);
}else{
acc[o[0]] = o[1];
}
return acc;
},{}));
console.log(data);
EDIT
Form your comment I assume that you are using a older version of node runtime where flat() is not present in the Array.prototype. So you can use the edited snippet below:
var arr1 = [ [ 'abandon', -2 ],
[ 'abandon', 1 ],
[ 'abandon', -2 ],
[ 'abduct', 1 ],
[ 'abduct', -2 ],
[ 'abduct', -2 ],
[ 'abhor', -3 ],
[ 'abhor', 1 ],
[ 'abhor', -1 ],
[ 'abil', 2 ],
[ 'abil', 4 ] ];
var arr2 = [ [ 'abandon' ],
[ 'abil' ],
[ 'abhor' ],
[ 'abduct' ],
['test'],
['hey'],
['testAgain'],
['array']];
//flatten using Array.prototype.concat
var lookup = new Set([].concat.apply([], arr2));
//If Set doesn't work use the array, but this will not be a constant time lookup
//var lookup = [].concat.apply([], arr2);
var mapping = arr1.filter(([word, val]) => lookup.has(word));
//If you are not using Set and going with an array, use Array.prototype.includes, so search won't be O(1)
//var mapping = arr1.filter(([word, val]) => lookup.includes(word));
var data = Object.entries(mapping.reduce((acc, o, i) => {
if(acc[o[0]]){
acc[o[0]] = Math.max(o[1], acc[o[0]]);
}else{
acc[o[0]] = o[1];
}
return acc;
},{}));
console.log(data);
I would do with as few loops as possible.
var arr1 = [ [ 'abandon', -2 ], [ 'abandon', 1 ], [ 'abandon', -2 ], [ 'abduct', 1 ], [ 'abduct', -2 ], [ 'abduct', -2 ], [ 'abhor', -3 ], [ 'abhor', 1 ], [ 'abhor', -1 ], [ 'abil', 2 ], [ 'abil', 4 ] ];
var arr2 = [ [ 'abandon' ], [ 'abil' ], [ 'abhor' ], [ 'abduct' ], ['test'], ['hey'], ['testAgain'], ['array']];
function getHighestResults(dataArr, filterArr) {
var name = ''; // higher readability in code and created outside
var number = -1; // for loops to avoid creating variables inside of them
function existsInObject(obj, name) {
return obj.hasOwnProperty(name);
}
function filterBasedOn(arr, obj) {
var filteredArr = [];
for (let i = 0; i < arr.length; i++) {
name = arr[i][0];
if (existsInObject(obj, name)) {
filteredArr.push([name, obj[name]]);
}
}
return filteredArr;
}
function getHighestValuesAsObj(arr) {
var dataObj = {};
for (let i = 0; i < arr.length; i++) {
name = arr[i][0];
number = arr[i][1];
if (!existsInObject(dataObj, name) || dataObj[name] < number) {
dataObj[name] = number;
}
}
return dataObj;
}
return filterBasedOn(filterArr, getHighestValuesAsObj(dataArr));
}
console.log(getHighestResults(arr1, arr2));

How to merge two 2 dimensional arrays with Jquery

I want to merge the oldData and newData. Need to show output by sorting date as ascending. If data is available in both, add as [date , oldValue , New value]. If data available in newData only then create like [ '2018-03-30', null, 5 ]
var oldData = [ [ '2018-04-01', 10 ], [ '2018-04-02', 20 ], [ '2018-04-03', 30 ] ];
var newData = [ [ '2018-03-30', 5 ], [ '2018-03-31', 6 ], [ '2018-04-01', 22 ] ];
The desired output would be:
[ [ '2018-03-30', null, 5 ], [ '2018-03-31', null, 6 ], [ '2018-04-01', 10, 22 ] , [ '2018-04-02', 20, null ] , [ '2018-04-03', 30, null ] ];
Please help me achieve this in jquery / java-script.
I'd do something like that:
let output = [];
oldData.map(e => output.push([new String(e[0]), e[1], null]));
for(const elem of newData) {
output.map(e => {
if(e[0] === elem[0]) {
e[2] = elem[1];
continue;
}
})
output.push([new String(elem[0]), null, elem[1]]);
}
You create new array with the values from the oldData, in a desired structure (I user new String() to make sure I don't just copy a reference - remove if not needed).
Then you loop over the elements of newData to see if ouptut already has an elem. with that date.
If so, you change the null inside it to a number from coresponding element.
If not, you just push a new one with given date, null and a number.
Remeber that this will work properly only when the items are unique!

How to remove comma from my array value?

hi pretty new to javascript.I am pretty confused in spliting my array value
console.log(arr)//[ [ [ 10, 0 ] ], [ [ 8, 0 ] ], [ [ 8, 0 ] ], [ [ 5, 2 ] ] ]
var line = "";
arr.forEach(e => {
e.forEach(f => line += "[" + f.join(",") + "],");
});
console.log(line);//[10,0],[8,0],[8,0],[5,2],
But i want my ouptput like this to do matrix addition
console.log(line);//[[10,0],[8,0],[8,0],[5,2]]
You can use map() for this.
var arr = [ [ [ 10, 0 ] ], [ [ 8, 0 ] ], [ [ 8, 0 ] ], [ [ 5, 2 ] ] ];
var result = arr.map(function(a) {
return a[0];
});
console.log(result)
You could do this by changing where the join happens and pre/app-ending some square brackets, e.g.
var line = arr.map(e => e.map(f => f.join(",")));
console.log('[' + line.join('],[') + ']');
// [10,0],[8,0],[8,0],[5,2]
I do have to ask though, why are you getting back a set of arrays each with a single value? Is it possible to avoid getting a dataset like that in the first place? You could avoid the double map/foreach that way.
For instance if you had one level less nesting in your source array the map line would become a little simpler
var arr = [ [ 10, 0 ], [ 8, 0 ], [ 8, 0 ], [ 5, 2 ] ];
var line = arr.map(f => f.join(","));
console.log('[' + line.join('],[') + ']');
This is of course if you want to specifically output the string for the array matrix, if you just wanted a flatter version of your original array then you could do:
var newList = arr.map(f => f[0]);
// [ [ 10, 0 ], [ 8, 0 ], [ 8, 0 ], [ 5, 2 ] ]

Categories

Resources