Elements of my array are duplicated with .map function - javascript

I'm triyng to mix two arrays with .map() and .filter(), but my elements are doubled, tripled and more.
My two arrays are,
a = [
[ "id", 1536 ],
[ "origin", "ModèleLogiciel" ],
[ "target", "ModèleDomaine" ],
[ "type", "CONCERNE" ],
[ "EAI", "reel" ]
]
and
b = [ "EAI", "Fréquence" ]
I want to add the values of the second array in the first one, like this :
a = [
[ "id", 1536 ],
[ "origin", "ModèleLogiciel" ],
[ "target", "ModèleDomaine" ],
[ "type", "CONCERNE" ],
[ "EAI", "reel" ],
[ "Fréquence", "" ]
]
I've done :
a.map((col) => {
return (
b.filter((x) => {
if (col[0] !== x) {
a.push([x, ""]);
}
})
);
});
and my result :
a = [
["id", 1536],
["origin", "ModèleLogiciel"],
["target", "ModèleDomaine"],
["type", "CONCERNE"],
["EAI", "reel"],
["Fréquence", ""],
["EAI", ""],
["Fréquence", ""],
["EAI", ""],
["Fréquence", ""],
["EAI", ""],
["Fréquence", ""],
];
I have to misuse the .map function, I presume. And I have trouble removing duplicates.
Someone have a solution for me :) ?

You should use concat
a.concat(b.map(x => [x, '']))
update:
maybe you want to add b value that only not exist in a. that's why you want to use filter.
you can do it like this:
a.concat(b.filter(x => a.find(y => y[0] == x) == null).map(x => [x, '']))

Use array spread to combine between array a, and the result of mapping array b to the required form:
const a = [["id",1536],["origin","ModèleLogiciel"],["target","ModèleDomaine"],["type","CONCERNE"]]
const b = [ "EAI", "Fréquence" ]
const result = [
...a, // add a
...b.map(v => [v, ""]) // transform b and add it
]
console.log(result)

You could map new arrays and push them to the goven array.
const
a = [["id", 1536], ["origin", "ModèleLogiciel"], ["target", "ModèleDomaine"], ["type", "CONCERNE"]],
b = ["EAI", "Fréquence"];
a.push(...b.map(value => [value, '']));
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0; }

First merge using spread operators, then using a map and create a new array.
I would also check if the given input is not an array.
var a = [
["id", 1536],
["origin", "ModèleLogiciel"],
["target", "ModèleDomaine"],
["type", "CONCERNE"],
];
var b = ["EAI", "Fréquence"];
var result = [...a, ...b].map((i) => i instanceof Array ? i : [i, ""]);
console.log(result)

You can use b.forEach() to push new array items into a:
const a = [["id", 1536], ["origin", "ModèleLogiciel"], ["target", "ModèleDomaine"], ["type", "CONCERNE"]];
const b = ["EAI", "Fréquence"];
b.forEach(x => a.push([x, ""]));
console.log(a);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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);

Concat all values inside a map

I've got a constant result like this :
result: Map<string, string[]>
When I do a console.log(result) the output is :
Map {
'toto' => [ 'a-1', 'a-2' ],
'tata' => [ 'b-1', 'b-2' ],
'titi' => [ 'c-1', 'c-2' ],
}
What I want to have, it's a constant globalResult with all values like this:
const globalResult = [ 'a-1', 'a-2','b-1','b-2','c-1','c-2' ]
How can I do this ?
Thanks
You can get map values into an array and then use flat() method on it like:
const myMap = new Map().set('toto', ['a-1', 'a-2']).set('tata', ['b-1', 'b-2'])
const arr = [...myMap.values()].flat()
console.log(arr)
You can use Array.from to covert map values into a flat array
const map = new Map();
map.set('a',11)
map.set('b',22)
map.set('c',33)
const array = Array.from(map.values())
console.log(array)
You could get the values of the properties and flat the arrays.
const
object = { toto: ['a-1', 'a-2'], tata: ['b-1', 'b-2'], titi: ['c-1', 'c-2'] },
array = Object.values(object).flat();
console.log(array);
Use forEach function.
const obj = {
'toto' : [ 'a-1', 'a-2' ],
'tata' : [ 'b-1', 'b-2' ],
'titi' : [ 'c-1', 'c-2' ],
}
const arr = [];
Object.values(obj).forEach(value=>arr.push(...value));
console.log(arr);

How can I combine elements of an array that are linear?

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' ]
// ]

Javascript/lodash how to remove empty arrays

I'm working with this structure:
[
[
{
"comments":"asd",
"movement":"Back Squat",
"userID":"wDHZv3OL55SIymHkhMUejNleNkx1",
"weight":"330"
}
],
[
{
"comments":"asd",
"movement":"Bench Press",
"userID":"wDHZv3OL55SIymHkhMUejNleNkx1",
"weight":"100"
}
],
[
{
"comments":"Comment",
"movement":"Clean",
"userID":"wDHZv3OL55SIymHkhMUejNleNkx1",
"weight":"195"
}
],
[
],
[
],
[
{
"comments":"Front squat comment alpha",
"movement":"Front Squat",
"userID":"wDHZv3OL55SIymHkhMUejNleNkx1",
"weight":"315"
}
],
[
],
[
],
[
],
[
],
[
],
[
{
"comments":"abc",
"movement":"Strict Press",
"userID":"wDHZv3OL55SIymHkhMUejNleNkx1",
"weight":"155"
}
]
]
This is the input I'm using in JSON format. As you can see there are multiple empty arrays.
How would I go about filtering through these arrays and remove the empty ones?
Use the native Array#filter or lodash's _.filter(), and keep the sub arrays with length other than 0.
Array#filter
var arrs = [[{"comments":"asd","movement":"Back Squat","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"330"}],[{"comments":"asd","movement":"Bench Press","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"100"}],[{"comments":"Comment","movement":"Clean","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"195"}],[],[],[{"comments":"Front squat comment alpha","movement":"Front Squat","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"315"}],[],[],[],[],[],[{"comments":"abc","movement":"Strict Press","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"155"}]];
var result = arrs.filter(function(sub) {
return sub.length;
});
console.log(result);
Lodash's _.filter() with _.size:
var arrs = [[{"comments":"asd","movement":"Back Squat","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"330"}],[{"comments":"asd","movement":"Bench Press","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"100"}],[{"comments":"Comment","movement":"Clean","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"195"}],[],[],[{"comments":"Front squat comment alpha","movement":"Front Squat","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"315"}],[],[],[],[],[],[{"comments":"abc","movement":"Strict Press","userID":"wDHZv3OL55SIymHkhMUejNleNkx1","weight":"155"}]];
var result = _.filter(arrs, _.size);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
If all the items in the top level array are arrays then you could lodash's reject with the isEmpty predicate.
let result = _.reject(data, _.isEmpty);
isEmpty will also return true for empty objects amongst other thing so if your top level array can contain such items then to just remove empty arrays you could compose a new function to return just empty arrays and use that as the predicate to reject:
let isEmptyArray = item => _.isArray(item) && _.isEmpty(item);
let result = _.reject(data, isEmptyArray);
Test each array in turn to see if it has a non-zero (truthy) length. If it does, put it in your new array.
var array_of_arrays = [[1], [1,1], [], [], [1]];
var array_of_non_empty_arrays = array_of_arrays.filter((array) => array.length);
console.log(array_of_non_empty_arrays);

How to assign Array of values as keys to another array of values?

What is the Best way to convert,
{
"columns":[
"name",
"color"
],
"values":[
[
"lion",
"yellow"
],
[
"crow",
"black"
]
]
}
into
{
"data":[
{
"name":"lion",
"color":"yellow"
},
{
"name":"crow",
"color":"black"
}
]
}
Rather than loop, Is there any function available ? Can I achieved it through something like extend() ?
You could use Object.assign with spread syntax ... for the parts.
var object = { columns: ["name", "color"], values: [["lion", "yellow"], ["crow", "black"]] },
result = { data: object.values.map(v => Object.assign(...object.columns.map((c, i) => ({[c]: v[i]})))) };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do do it with combination of map and reduce. Reducing original columns array will allow to code to work with any number of columns, it will pick up corresponding value by index:
const result = {data: data.values.map(el => {
return data.columns.reduce((prev, curr, index) => {
prev[curr] = el[index]
return prev
}, {})
})}
Check the demo below.
const data = {
"columns":[
"name",
"color"
],
"values":[
[
"lion",
"yellow"
],
[
"crow",
"black"
]
]
}
const result = {data: data.values.map(el => {
return data.columns.reduce((prev, curr, index) => {
prev[curr] = el[index]
return prev
}, {})
})}
console.log(result)
You can get vales of .columns array using destructuring assignment, spread element; for..of loop to assign computed properties of .columns array as strings as properties of objects at data array by iterating .values property of original object, assign value of each array as value of created object
let obj = {
"columns":[
"name",
"color"
],
"values":[
[
"lion",
"yellow"
],
[
"crow",
"black"
]
]
}
let [res, key, value] = [{data:Array()}, ...obj.columns];
for (let [a, b] of [...obj.values]) res.data.push({[key]:a, [value]:b});
console.log(res);

Categories

Resources