I need help sorting this out, I tried object.keys with map, but can't get too far, so, I have this object and each key has an array:
const first = {
"apples": [
"5.78",
"3.96",
"3.71"
],
"oranges": [
"54.25",
"41.29",
"33.44"
],
"cucumbers": [
"97.28",
"97.13",
"95.95"
],
"carrots": [
"6.48",
"5.1",
"4.65"
]
}
and I need to sort it out and get a new array of objects like this one:
const second = [
{
"apples": "5.78",
"oranges": "54.25",
"cucumbers": "97.28",
"carrots": "6.48"
},
{
"apples": "3.96",
"oranges": "41.29",
"cucumbers": "97.13",
"carrots": "5.1"
},
{
"apples": "3.71",
"oranges": "33.44",
"cucumbers": "95.95",
"carrots": "4.65"
}
]
Thank you very much!!
Please ensure that you share with us how you attempted to solved this problem first, so that we know what all you've already tried.
That said, we'll help you out this time. You can create the second array using Object.entries():
const first = {
"apples": [
"5.78",
"3.96",
"3.71"
],
"oranges": [
"54.25",
"41.29",
"33.44"
],
"cucumbers": [
"97.28",
"97.13",
"95.95"
],
"carrots": [
"6.48",
"5.1",
"4.65"
]
}
const second = Object.entries(first).reduce((res, [key, arr]) => {
arr.forEach((val, i) => {
if (!res[i]) res[i] = {};
res[i][key] = val;
});
return res;
}, []);
console.log(second);
// Output
[
{
"apples": "5.78",
"oranges": "54.25",
"cucumbers": "97.28",
"carrots": "6.48"
},
{
"apples": "3.96",
"oranges": "41.29",
"cucumbers": "97.13",
"carrots": "5.1"
},
{
"apples": "3.71",
"oranges": "33.44",
"cucumbers": "95.95",
"carrots": "4.65"
}
]
const d = {"apples":["5.78","3.96","3.71"],"oranges":["54.25","41.29","33.44"],"cucumbers":["97.28","97.13","95.95"],"carrots":["6.48","5.1","4.65"]}
const r = Object.values(d)[0]
.map((_,i)=>Object.fromEntries(Object.entries(d).map(([k,v])=>[k,v[i]])))
console.log(r)
Related
Here is my Function which turns timestamps to seconds,
const convertor = (x) => {
const result = x.split(':');
const final =
parseInt(result[0] * 60) +
parseInt(result[1] * 60) +
parseInt(result[2]) -
1.2;
return final;
};
input = 00:01:02.330
result: 62.330
How can I implement it on a nested array like this?
array = [ [ 00:01:02.330],[00:01:04.550],[01:11:02.330] ], [ [00:01:02.330],[00:01:02.330] ] , [ [00:01:02.330],[00:01:02.330],[00:01:02.330] ] ]
I want to preserve its nested structure so the result should be:
[ [ 22.3],[28.5],[903.50] ], [ [1252.3],[62.2] ] , [ [654.25],[965.25],[1254.32] ] ]
You can write a wrapper that accepts a function and an array, and maps over the array-- if the item is an array, it recurses; otherwise, it passes the item into the passed function-- this allows you to process nested arrays of any arbitrary depth and retain the desired structure:
const convertor = (x) => {
const result = x.split(':');
const final =
parseInt(result[0] * 60) +
parseInt(result[1] * 60) +
parseInt(result[2]) -
1.2;
return final;
};
const recursiveNestedMapper = (fn, arr) => {
const output = arr.map((item) => {
if (Array.isArray(item)) {
return recursiveNestedMapper(fn, item);
} else {
return fn(item);
}
});
return output;
}
const inputArray = [
[
['00:01:02.330'],
['00:01:04.550'],
['01:11:02.330']
],
[
['00:01:02.330'],
['00:01:02.330']
],
[
['00:01:02.330'],
['00:01:02.330'],
['00:01:02.330']
]
];
const outArray = recursiveNestedMapper(convertor, inputArray);
console.log(outArray);
Not sure why you're keeping the timestamps in an array when it's the only element, but you can get the desired output by chaining map()
const convertor = (x) => {
const result = x[0].split(':');
const final =
parseInt(result[0] * 60) +
parseInt(result[1] * 60) +
parseInt(result[2]) -
1.2;
return final;
};
const array = [
[ [ '00:01:02.330' ], [ '00:01:04.550' ], [ '01:11:02.330' ] ],
[ [ '00:01:02.330' ], [ '00:01:02.330' ] ],
[ [ '00:01:02.330' ], [ '00:01:02.330' ], [ '00:01:02.330' ] ]
];
const output = array.map(a => a.map(b => convertor(b)));
console.log(output);
[
[
60.8,
62.8,
720.8
],
[
60.8,
60.8
],
[
60.8,
60.8,
60.8
]
]
I have the following data structure and this data needs to be sorted by the sum of the first two indexes of an array in "104".
{
"data":{
"Org 1":{
"102":[
0.1444,
0.1551,
0.2369,
0.3353,
0.1282
],
"104":[
0.309,
0.3483,
0.218,
0.0657,
0.059
]
},
"Org 2":{
"102":[
0.19444444444444448,
0.1388888888888889,
0.19444444444444448,
0.33333333333333326,
0.1388888888888889
],
"104":[
0.20588235294117646,
0.38235294117647056,
0.14705882352941177,
0.14705882352941177,
0.1176470588235294
],
},
"Org 3":{
"102":[
0.0967741935483871,
0.2903225806451613,
0.16129032258064516,
0.3548387096774194,
0.0967741935483871
],
"104":[
0.44,
0.24,
0.2,
0.04,
0.08
]
}
}
}
How can I make this work? Can someone please help?
This is what I tried so far but it's not working as expected
let orgs = Object.keys(data);
let options = [];
let selection = orgs.forEach((data, d) => {
data["104"].forEach((val, i) => {
options[i].data.push(val);
})
});
First, we need to transform the data into an array for sorting.
Then define our own compare function as our requirement.
Finally, sort the array.
Run the snippet to check the result.
Solution:
var data = {
"Org 1":{
"102":[
0.1444,
0.1551,
0.2369,
0.3353,
0.1282
],
"104":[
0.309,
0.3483,
0.218,
0.0657,
0.059
]
},
"Org 2":{
"102":[
0.19444444444444448,
0.1388888888888889,
0.19444444444444448,
0.33333333333333326,
0.1388888888888889
],
"104":[
0.20588235294117646,
0.38235294117647056,
0.14705882352941177,
0.14705882352941177,
0.1176470588235294
],
},
"Org 3":{
"102":[
0.0967741935483871,
0.2903225806451613,
0.16129032258064516,
0.3548387096774194,
0.0967741935483871
],
"104":[
0.44,
0.24,
0.2,
0.04,
0.08
]
}
};
const transformedData = [];
Object.keys(data).forEach(
f => {
transformedData.push(data[f]);
}
)
function compare(a, b) {
var arrA = a["104"];
var arrB = b["104"];
if (arrA[0]+arrA[1] < arrB[0]+arrB[1]) {
return -1;
}
if (arrA[0]+arrA[1] > arrB[0]+arrB[1]) {
return 1;
}
return 0;
}
transformedData.sort(compare);
console.log(transformedData);
Breakdown:
(0.205882352941176 + 0.38235294117647) < (0.309 + 0.3483) < (0.44 + 0.24)
I have an object, which has 2 objects whithin and some properties of interest.
myObject = {
"chart":{
"data":[
{
"name":"First",
"x":[
"2000-01-01T00:00:00",
"2000-02-01T00:00:00",
"2000-03-01T00:00:00",
],
"y":[
1,
2,
3,
],
"type":"scatter"
},
{
"name":"Second",
"x":[
"2000-01-01T00:00:00",
"2000-02-01T00:00:00",
"2000-03-01T00:00:00",
],
"y":[
1,
2,
3,
],
"type":"scatter"
},
],
"otherKey":{
"whatever":"line"
}
},
};
I'm trying to create a new "object" which is an array of objects, and the only keys of interest are name and point, with point being an array of x and y combined.
newObject = [
{
"name":"First",
"point":[
["2000-01-01T00:00:00", 1],
["2000-02-01T00:00:00", 2],
["2000-03-01T00:00:00", 3],
],
},
{
"name":"Second",
"point":[
["2000-01-01T00:00:00", 1],
["2000-02-01T00:00:00", 2],
["2000-03-01T00:00:00", 3],
],
},
];
I'm trying to use map and filter function but I'm getting lost somewhere in the middle.
newObject = myObject.chart.data.map((value) => {
return [
value.x,
value.y
]
});
I think I need to concatenate them properly.
I'm a JS begginer, any tip or guidance would help, thanks.
you are missing how to combine those arrays of x and y, this implementation should help you
newObject = myObject.chart.data.map((value) => {
return {
name: value.name,
point: combine(value.x, value.y)
}
});
function combine(arr1, arr2) {
let ans = [];
for(let i = 0; i < arr1.length; i++) {
ans.push([arr1[i], arr2[i]])
}
return ans;
}
You can make use of map.
myObject = { "chart":{ "data":[ { "name":"First", "x":[ "2000-01-01T00:00:00", "2000-02-01T00:00:00", "2000-03-01T00:00:00", ], "y":[ 1, 2, 3, ], "type":"scatter" }, { "name":"Second", "x":[ "2000-01-01T00:00:00", "2000-02-01T00:00:00", "2000-03-01T00:00:00", ], "y":[ 1, 2, 3, ], "type":"scatter" }, ], "otherKey":{ "whatever":"line" } },};
result = myObject.chart.data.map(({name, ...rest})=>{
point = rest.x.map((k,i)=>[k,rest.y[i]]);
return {name, point};
});
console.log(result);
I am trying to format a string to produce a new string in the correct format:
I have the following strings (left) which should be formatted to match (right):
[ 'xx9999', 'XX-99-99' ],
[ '9999xx', '99-99-XX' ],
[ '99xx99', '99-XX-99' ],
[ 'xx99xx', 'XX-99-XX' ],
[ 'xxxx99', 'XX-XX-99' ],
[ '99xxxx', '99-XX-XX' ],
[ '99xxx9', '99-XXX-9' ],
[ '9xxx99', '9-XXX-99' ],
[ 'xx999x', 'XX-999-X' ],
[ 'x999xx', 'X-999-XX' ],
[ 'xxx99x', 'XXX-99-X' ],
[ 'x99xxx', 'X-99-XXX' ],
[ '9xx999', '9-XX-999' ],
[ '999xx9', '999-XX-9' ]
I have tried the following but cannot get it to work correctly:
const formatLp = (userInput) => {
if (userInput) {
return userInput.toUpperCase().match(/[a-z]+|[^a-z]+/gi).join('-');
}
}
This works for some of them, such as 99xxx9 but not others such as xx9999
any help would be appreciated.
Use .replace twice - once to insert a - between 4 repeated digits/non-digits, and once to insert a - between digits and alphabetical characters:
const arr = [
[ 'xx9999', 'XX-99-99' ],
[ '9999xx', '99-99-XX' ],
[ '99xx99', '99-XX-99' ],
[ 'xx99xx', 'XX-99-XX' ],
[ 'xxxx99', 'XX-XX-99' ],
[ '99xxxx', '99-XX-XX' ],
[ '99xxx9', '99-XXX-9' ],
[ '9xxx99', '9-XXX-99' ],
[ 'xx999x', 'XX-999-X' ],
[ 'x999xx', 'X-999-XX' ],
[ 'xxx99x', 'XXX-99-X' ],
[ 'x99xxx', 'X-99-XXX' ],
[ '9xx999', '9-XX-999' ],
[ '999xx9', '999-XX-9' ]
];
arr.forEach(([str]) => {
const result = str.toUpperCase()
.replace(/\d{4}|\D{4}/, substr => `${substr.slice(0, 2)}-${substr.slice(2)}`)
.replace(/[a-z]{4}|\d(?=[a-z])|[a-z](?=\d)/gi, '$&-');
console.log(result);
});
You can also do it by matching and then joining - match 3 non-digits, or 3 digits, or 1-2 non-digits, or 1-2 digits:
const arr = [
[ 'xx9999', 'XX-99-99' ],
[ '9999xx', '99-99-XX' ],
[ '99xx99', '99-XX-99' ],
[ 'xx99xx', 'XX-99-XX' ],
[ 'xxxx99', 'XX-XX-99' ],
[ '99xxxx', '99-XX-XX' ],
[ '99xxx9', '99-XXX-9' ],
[ '9xxx99', '9-XXX-99' ],
[ 'xx999x', 'XX-999-X' ],
[ 'x999xx', 'X-999-XX' ],
[ 'xxx99x', 'XXX-99-X' ],
[ 'x99xxx', 'X-99-XXX' ],
[ '9xx999', '9-XX-999' ],
[ '999xx9', '999-XX-9' ]
];
arr.forEach(([str]) => {
const result = str.toUpperCase()
.match(/[a-z]{3}|\d{3}|[a-z]{1,2}|\d{1,2}/gi)
.join('-');
console.log(result);
});
I've just implemented this using Stack. Here is the function. You just need to pass the string to this function.
const convert = (str) => {
let stack = str.split('').reduce((newArr, char, index) => {
if(index !== 0 && newArr[newArr.length-1] !== char) {
newArr.push('-');
newArr.push(char);
return newArr;
} else {
newArr.push(char);
return newArr;
}
},[])
return stack.join('').toUpperCase();
}
// Here you can check this in action
const convert = (str) => {
let stack = str.split('').reduce((newArr, char, index) => {
if(index !== 0 && newArr[newArr.length-1] !== char) {
newArr.push('-');
newArr.push(char);
return newArr;
} else {
newArr.push(char);
return newArr;
}
},[])
return stack.join('').toUpperCase();
}
const strings = [ 'xx9999','9999xx','99xx99','xx99xx','xxxx99','99xxxx','99xxx9','9xxx99','xx999x','x999xx','xxx99x','x99xxx','9xx999','999xx9',];
strings.map(string => console.log(convert(string)))
My data looks like:
[ [ '0s', '0.200s' ],
[ '0.200s', '0.600s' ],
[ '1.600s', '2.500s' ],
[ '3.500s', '3.900s' ],
[ '3.900s', '4.400s' ],
[ '4.400s', '4.600s' ],
[ '4.600s', '4.700s' ],
[ '4.700s', '5.200s' ],
[ '5.200s', '5.400s' ],
[ '5.400s', '5.800s' ],
[ '5.800s', '6.100s' ],
[ '6.100s', '6.800s' ],
[ '6.800s', '7s' ],
[ '7s', '7.300s' ],
[ '7.300s', '7.500s' ]
]
The first element ends at 0.200s which is where the second element begins. So I want those 2 to combine to be ['0s', '0.600s'].
The next element doesn't start where this one ends, so it should continue on. Ultimately, the result should look like:
[ [ '0s', '0.600s' ],
[ '1.600s', '2.500s' ],
[ '3.500s', '7.500s' ]
]
I am trying to do it recursively, but it's giving errors. Here's my function:
function combineStartsEnds(timecodes) {
if (timecodes[0][1] === timecodes[1][0]) {
let combined = [
[timecodes[0][0], timecodes[1][1]]
].concat(_.slice(timecodes, 2));
return combineStartsEnds(combined);
} else {
return timecodes[0].concat(combineStartsEnds(_.slice(timecodes, 1)));
}
};
This gives an error:
TypeError: Cannot read property '0' of undefined
Any ideas on how to accomplish this?
You are missing brackets here, this:
return timecodes[0].concat(...)
must be:
return [timecodes[0]].concat(...)
Additionally you need a base case to end the recursion:
function combineStartsEnds(timecodes) {
if(!timecodes.length) return [];
How I would do that:
function combineStartsEnds(timecodes) {
const result = []; let previous = [];
for(const [start, end] of timecodes) {
if(start === previous[/*end*/ 1]) {
previous[/*end*/ 1] = end;
} else {
result.push(previous = [start, end]);
}
}
return result;
}
You can also do this with reduce.
const times = [ [ '0s', '0.200s' ],
[ '0.200s', '0.600s' ],
[ '1.600s', '2.500s' ],
[ '3.500s', '3.900s' ],
[ '3.900s', '4.400s' ],
[ '4.400s', '4.600s' ],
[ '4.600s', '4.700s' ],
[ '4.700s', '5.200s' ],
[ '5.200s', '5.400s' ],
[ '5.400s', '5.800s' ],
[ '5.800s', '6.100s' ],
[ '6.100s', '6.800s' ],
[ '6.800s', '7s' ],
[ '7s', '7.300s' ],
[ '7.300s', '7.500s' ]
];
const merged = times.reduce((acc, [t3, t4]) => {
const [t1, t2] = acc[acc.length - 1] || [null, null];
if (t2 === t3) {
acc.pop();
acc.push([t1, t4]);
} else {
acc.push([t3, t4]);
}
return acc;
}, []);
console.log(merged);
You can also try below method to get your desired result.
(1) Flatten the array, you will get
arr.flat()
["0s", "0.200s", "0.200s", "0.600s", "1.600s", "2.500s", "3.500s", "3.900s", "3.900s", "4.400s", "4.400s", "4.600s", "4.600s", "4.700s", "4.700s", "5.200s", "5.200s", "5.400s", "5.400s", "5.800s", "5.800s", "6.100s", "6.100s", "6.800s", "6.800s", "7s", "7s", "7.300s", "7.300s", "7.500s"]
(2) Filter and remove elements if same exists before and after it's position, you will get
arr.flat().filter((d,i,c) => d != c[i-1] && d != c[i+1])
["0s", "0.600s", "1.600s", "2.500s", "3.500s", "7.500s"]
(3) Reduce the above result to the format you need
arr.flat()
.filter((d,i,c) => d != c[i-1] && d != c[i+1])
.reduce((res, d, i, c) => (i%2 == 0 && res.push([d, c[i+1]]) , res) , [])
[["0s", "0.600s"]
["1.600s", "2.500s"]
["3.500s", "7.500s"]]
How about using a Map():
const data = [
['0s', '0.200s'],
['0.200s', '0.600s'],
['1.600s', '2.500s'],
['3.500s', '3.900s'],
['3.900s', '4.400s'],
['4.400s', '4.600s'],
['4.600s', '4.700s'],
['4.700s', '5.200s'],
['5.200s', '5.400s'],
['5.400s', '5.800s'],
['5.800s', '6.100s'],
['6.100s', '6.800s'],
['6.800s', '7s'],
['7s', '7.300s'],
['7.300s', '7.500s']
];
var data_map = new Map(data);
for (var [key, value] of data_map) {
while (data_map.has(value)) {
var new_value = data_map.get(value);
data_map.set(key, new_value);
data_map.delete(value);
value = new_value;
}
}
data_map.forEach((value, key) => console.log(`[${key}, ${value}]`));
You could reduce the array with a single loop by checking the values and update either the last array or push a new array to the result set.
var data = [['0s', '0.200s'], ['0.200s', '0.600s'], ['1.600s', '2.500s'], ['3.500s', '3.900s'], ['3.900s', '4.400s'], ['4.400s', '4.600s'], ['4.600s', '4.700s'], ['4.700s', '5.200s'], ['5.200s', '5.400s'], ['5.400s', '5.800s'], ['5.800s', '6.100s'], ['6.100s', '6.800s'], ['6.800s', '7s'], ['7s', '7.300s'], ['7.300s', '7.500s']],
combined = data.reduce((r, [a, b]) => {
var last = r[r.length - 1];
if (last && a === last[1]) {
last[1] = b;
} else {
r.push([a, b]);
}
return r;
}, []);
console.log(combined);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One way to do it using recursion –
const start = ([ a, b ]) =>
a
const end = ([ a, b ]) =>
b
const join = ([ a, b, ...rest ]) =>
// base: no `a`
a === undefined
? []
// inductive: some `a`
: b === undefined
? [ a ]
// inductive: some `a` and some `b` (joinable)
: end (a) === start (b)
? join ([ [ start (a), end (b) ], ...rest ])
// inductive: some `a` and some `b` (non-joinable)
: [ a, ...join ([ b, ...rest ]) ]
const data =
[ [ '0s', '0.200s' ]
, [ '0.200s', '0.600s' ]
, [ '1.600s', '2.500s' ]
, [ '3.500s', '3.900s' ]
, [ '3.900s', '4.400s' ]
, [ '4.400s', '4.600s' ]
, [ '4.600s', '4.700s' ]
, [ '4.700s', '5.200s' ]
, [ '5.200s', '5.400s' ]
, [ '5.400s', '5.800s' ]
, [ '5.800s', '6.100s' ]
, [ '6.100s', '6.800s' ]
, [ '6.800s', '7s' ]
, [ '7s', '7.300s' ]
, [ '7.300s', '7.500s' ]
]
console.log (join (data))
// [ [ '0s', '0.600s' ]
// , [ '1.600s', '2.500s' ]
// , [ '3.500s', '7.500s' ]
// ]