How to process an array one by one in javascript? - javascript

I have an array of values in a stream and you wish to pipe it such that it will emit the arrays values individually, one by one and wait for them all to be completed before processing another array
// This is the array:
let arr = [[1,2,3], [4,5,6]];
let data = arr.filter( (value) => {
let newdata = value.filter((newVal, index) => {
if (newVal !== value[index]) {
return '' ;
}
});
});
console.log(data);
// Output: []
// Expected output: [[], []]

arr.map(x => x.map((y, index) => {if(y !== y[index]){return ''}}))
This will return [["", "", ""], ["", "", ""]]
For [[], []] filter out those blank strings:
arr.map(x => x.map((y, index) => {if(y !== y[index]){return ''}}).filter(z => z !== ""))

At root use Map instead of filter:
let arr = [[1,2,3], [4,5,6]];
let data = arr.map( (value) => {
let newdata = value.filter((newVal, index) => {
if (newVal !== value[index]) {
return '' ;
}
});
return newdata;
});
console.log(data);

Related

How can I extract from an array of arrays all the arrays that have the same value in their first field?

The following function elegantly finds duplicates in 1-dimensional arrays:
const findDuplicates = (dataArray) => {
const duplicates = dataArray.filter((e, index, arr) => arr.indexOf(e) !== index);
return (duplicates);
};
When I send it (for example) this array
['123456', '787877', '763223', '787877', '854544'] it returns ['787877'].
What I need is something similar that works for a 2-d array so (for instance) inputting
[
['123456', 'Smith'],
['787877', 'Jones'],
['763223', 'Waldo'],
['787877', 'Quagmire'],
['854544', 'Miller']
]
returns
[['787877', 'Jones'], ['787877', 'Quagmire']]
(To be clear, I'm only interested in whether the 1st field of each sub-array is a dupe.)
const findDuplicates = (dataArray) => {
const duplicates = dataArray.filter((e, index, arr) => {
return arr.some((val, i) => (index !== i && val[0] === e[0]))
})
return (duplicates);
};
const result = findDuplicates([
['123456', 'Smith'],
['787877', 'Jones'],
['763223', 'Waldo'],
['787877', 'Quagmire'],
['854544', 'Miller']
])
console.log(result)
You could take an object and use a boolean values to indicae duplicates. Then filter the array.
const
findDuplicates = data => {
const
keys = data.reduce((r, [v]) => {
r[v] = r[v] !== undefined;
return r;
}, {});
return data.filter(([v]) => keys[v]);
},
data = [['123456', 'Smith'], ['787877', 'Jones'], ['763223', 'Waldo'], ['787877', 'Quagmire'], ['854544', 'Miller']],
result = findDuplicates(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Invert key value in js object

I can't figure out how I can change :
{"first":["de"], "second":["ab","de"], "third":["de"]}
to:
{"de":["first", "second", "third"], "ab":["second"]}
I want to associate unique values with list of containing keys. What I tried(but I think I'm far from it):
const data = {
"first":["de"],
"second":["ab","de"],
"third":["de"]
}
console.log(
Object
.keys(data).reduce(function(obj, key) {
obj[data[key]] = key;
return obj;
}, {})
)
Thanks for your help!
Object.entries to get it into an array, reduce to build the new object, and forEach to loop over the array
const o = {"first":["de"], "second":["ab","de"], "third":["de"]}
const result = Object.entries(o).reduce((obj, [key, arr])=>{
arr.forEach(lng => {
obj[lng] = obj[lng] || [];
obj[lng].push(key);
})
return obj
}, {});
console.log(result);
You have to loop the array and for each item in the array check if an array for that value exists in the accumulator or not before adding it:
let result = Object.entries(data).reduce((acc, [key, arr]) => { // for each key-array of the original object
arr.forEach(value => { // for each value in the array
acc[value] = acc[value] || []; // create an array in the output object if it doesn't already exist
acc[value].push(key); // push the key to it
});
return acc;
}, {});
I also used Object.entries with each entry desctuctured as [key, arr] so I don't have to use the extra [key] to get the array while using Object.keys.
Demo:
let data = {"first":["de"], "second":["ab","de"], "third":["de"]};
let result = Object.entries(data).reduce((acc, [key, arr]) => {
arr.forEach(value => {
acc[value] = acc[value] || [];
acc[value].push(key);
});
return acc;
}, {});
console.log(result);
On reduce callback, data[key] is an array of string values. So it is needed to loop that data[key] array values and assign value for each array item.
const data = {
"first":["de"],
"second":["ab","de"],
"third":["de"]
}
console.log(
Object.keys(data).reduce(function(obj, key) {
data[key].forEach((val) => {
obj[val] ? obj[val].push(key) : obj[val] = [ key ];
});
return obj;
}, {})
)
Try this (naive solution), if this works for you
const data = { first: ["de"], second: ["ab", "de"], third: ["de"] };
let dataMap = new Map();
Object.keys(data).forEach((key) => {
data[key].forEach((val) => {
if (dataMap.has(val)) {
dataMap.set(val, [...dataMap.get(val), key]);
} else {
dataMap.set(val, [key]);
}
});
});
let nData = [];
dataMap.forEach((value, key) => {
nData.push({
[key]: value
});
});
console.log(nData);
You could take a double reduce with the entries.
const
data = { first: ["de"], second: ["ab", "de"], third: ["de"] },
result = Object
.entries(data)
.reduce((o, [value, keys]) => keys.reduce((q, key) => {
(q[key] ??= []).push(value);
return q;
}, o), {});
console.log(result);
I'm not using reduce but here's a "bruteforce" for your problem which works:
res = {};
Object.keys(data).forEach(key => {
data[key].forEach(el => {
if (! res[el])
res[el] = [];
if (! res[el].includes(key))
res[el].push(key);
})
});

Remove duplicates within the output of a reduce function

I am outputting the matched value of projects when the name of my logo matches the items object within projects with the help of a reduce function. However, whenever I click on multiple logos that both match project.items I am rendering duplicates.
Here is my code:
logos.reduce((acc, logo) => {
if (logo.active) {
Object.values(projects).forEach((proj) => {
if (Object.values(proj.items).includes(logo.name)) {
console.log(acc)
acc.push((<Project title={proj.title} routeName={proj.routeName} items={proj.items} description={proj.description}/>));
}
});
}
return acc
}, [])
My first idea was to create another array, run a for loop and iterate through the values like: filteredValues[i].props.title and push the contents of that loop to an array. I ran run a reduce on that array like this but I was not able to eliminate the duplicate:
const filteredArr = arr.reduce((acc, current) => {
const x = acc.find(item => item.title === current.title);
if (!x) {
return acc.concat([current]);
} else {
return acc;
}
}, []);
Anyway, here's the output of acc which I am using to render my Project component
May be below code is what you need.
const filteredArr = this.getUnique(arr, 'title');
getUnique(arr, comp) {
const unique = arr.map(e => e[comp]).map((e, i, final) => final.indexOf(e) === i && i).filter((e) => arr[e]).map(e => arr[e]);
return unique;
}
Steps involve is to:
Store the comparison values in array "arr.map(e => e[comp])"
Store the indexes of the unique objects ".....).map((e, i, final) => final.indexOf(e) === i && i)"
Eliminate the false indexes & return unique objects ".....).filter((e) => arr[e]).map(e => arr[e])"
You can write your original loop like this
logos
.reduce((acc, logo) => {
if (logo.active) {
Object.values(projects).forEach((proj) => {
if (
Object.values(proj.items).includes(logo.name) &&
!acc.find((item) => item.value === logo.name)
) {
console.log(acc);
acc.push({
value: logo.name,
component: (
<Project
title={proj.title}
routeName={proj.routeName}
items={proj.items}
description={proj.description}
/>
),
});
}
});
}
return acc;
}, [])
.map((values) => values.component);
You can use the Map object to filter out duplicates.
let arrFiltered = [];
// form map of unique arr items
const arrMap = new Map();
arr.forEach(item => arrMap.set(item.title, item));
// form array of all items in map
arrMap.forEach(item => arrFiltered.push(item));
I had to run a reduce function outside of the original forEach loop and check those values with a some function.
logos.reduce((acc, logo) => {
if (logo.active) {
Object.values(projects).forEach((proj) => {
if (Object.values(proj.items).includes(logo.name)) {
console.log(acc)
acc.push((<Project title={proj.title} routeName={proj.routeName} items={proj.items} description={proj.description}/>));
}
});
acc = acc.reduce(function (p, c) {
if (!p.some(function (el) { return el.props.title === c.props.title; })) p.push(c);
return p;
}, []);
}
return acc
}, [])

reduce inside function returns undefined (?)

in this sample using reduce on array of objects works fine but when i insert it all into a function it starts to return undefined... it probably has to do with me not understanding how returning stuff from functions works
const egArrOfObj = [
{
name:'tomato',
},
{
name:'potato',
},
];
console.log(
egArrOfObj
.reduce((acc, curr) => {
return [...acc, curr.name]
} ,[] )
);
const namesFunction = (arrOfObj) => {
arrOfObj
.reduce((acc, curr) => {
return [...acc, curr.name]
} ,[] )
};
const names = namesFunction(egArrOfObj);
console.log(names)
If you add the return statement into your function then it will work as well.
Like the following:
const egArrOfObj = [{
name:'tomato',
},
{
name:'potato',
}];
const namesFunction = (arrOfObj) => {
return arrOfObj.reduce((acc, curr) => {
return [...acc, curr.name]
}, [])
};
console.log(namesFunction(egArrOfObj));
I hope that helps!

Javascript filter but return keys rather than values

This function works fine but I don't want it to return the values, but the keys:
const search = [2342,1900,1800,2310]
search = search.filter(function (el) { return el > 2200; });
So it should return [0,3] rather than [2342,2310]
You can get the keys, then use them to access the array, and filter based on that:
const search = [2342,1900,1800,2310];
const result = Object.keys(search)
.filter(key => search[key] > 2200)
.map(key => Number(key))
console.dir(result)
Or, for something more interesting:
const search = [2342,1900,1800,2310];
const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x);
const filter = f => a => a.filter(f);
const map = f => a => a.map(f);
const toPairs = o => Object.keys(o)
.map(k => [k, o[k]]);
const take = i => a => a[i];
const gte = a => b => b >= a;
const toNumber = x => Number(x);
const bigEnough = gte(2200);
const itemOneIsBigEnough = pipe(
take(1),
bigEnough
);
const getTheFirstItemAsANumber = pipe(take(0), toNumber);
const doTheThing = pipe(
toPairs,
filter(
itemOneIsBigEnough
),
map(getTheFirstItemAsANumber),
);
const result = doTheThing(search);
console.dir(result);
The easiest way is to just Array#reduce the items:
const search = [2342,1900,1800,2310]
const result = search.reduce(function (result, el, index) {
if(el > 2200) {
result.push(index);
}
return result;
}, []);
console.log(result);
You could get the keys and filter by value check.
const
search = [2342, 1900, 1800, 2310],
indices = [...search.keys()].filter(i => search[i] > 2200);
console.log(indices);
let search = [2342, 1900, 1800, 2310]
search = search.map((el, i) => {
if (el > 2200) return i;
}).filter(el => el !== undefined);
console.log(search);

Categories