Filter array items using forEach - javascript

I have one question about filter array in forEach. So I would like filter (bigger than in example) array using outside variable filterKey. I think that my function is correct by after filtered newArr is undefined. Could you explain what is incorrect?
var filterKey = 123456,
var array = [{
ratings:{ users:[id: 123456]}, user: xyz
},
{
ratings:{users:[id:9787389023]}, user:zyx
}],
And my filter function
var newArr = array.forEach((ele) =>
ele.ratings.users.filter((newEl) =>
newEl.id == filterKey))

Use array.filter method
let array = [
{
id: 123456, user: 'xyz'
},
{
id:9787389023, user: 'zyx'
},
{
id: 123456, user: 'che'
}
]
let newArray = array.filter((element) => element.id === 123456)
console.log(newArray)

Use .filter and you'll be able to filter your result set without using foreach since it'll loop across the array.
var find = 123456;
var arr = [
{
id: 123456,
user: 'john'
},
{
id: 9787389023,
user: 'leah'
}
];
var results = arr.filter(function(node) {
return node.id === find;
});
console.log(results);

Related

Handle object array without duplicates

I use React for my front-end web app. When I call back-end API, I got this array:
[
{
id: 1,
fullname: ABC,
email: abc#gmail.com
...
},
{
id: 2,
fullname: DEF,
email: def#gmail.com
...
},
{
id: 2,
fullname: DEF,
email: def#gmail.com
...
},
{
id: 3,
fullname: GHI,
email: ghi#gmail.com
...
},
{
id: 1,
fullname: ABC,
email: abc#gmail.com
...
}
]
Now, I need to create a new array from this old array but just contain id and fullname and not duplicates. I have try this code:
const oldArray = //this is the array above
const temp = [];
for (let i = 0; i < oldArray .length; i++) {
temp.push({
value: oldArray [i]._id,
display: oldArray [i].fullname
});
}
const newArray = Array.from(new Set(temp));
The result I receive:
[
{
value: 1,
display: ABC
},
{
value: 2,
display: DEF
},
{
value: 2,
display: DEF
},
{
value: 3,
display: GHI
},
{
value: 1,
display: ABC
}
]
As you can see, the result is still duplicated. How can I fix it?
You can use Array#filter with a Set to store ids that were already found.
const arr=[{id:1,fullname:"ABC",email:"abc#gmail.com"},{id:2,fullname:"DEF",email:"def#gmail.com"},{id:2,fullname:"DEF",email:"def#gmail.com"},{id:3,fullname:"GHI",email:"ghi#gmail.com"},{id:1,fullname:"ABC",email:"abc#gmail.com"}];
let ids = new Set, res = arr.filter(x => !ids.has(x.id) && ids.add(x.id));
console.log(res);
const tempArray=[];
const filteredArr = oldArray.filter(value =>{
if(!tempArray.includes(value.id)) {
tempArray.push(value.id)
return true
}
})
Create a tempArray, loop over the array and checks if a value exist in tempArr if not push the value into the tempArr and return true(or value)
I know short answer but, use a Set() on the receiving end. Whenever you add an item to a set, use Set.add - it makes sure if it's a duplicate, it won't be added to the set. Sets have similar capability as arrays, but cannot contain duplicates.

Javascript: Filter array of objects

What am I doing wrong here?
var locations = [
{ id: 1, name: 'N'},
{ id: 2, name: 'P'}
]
var employee = { location_id: 1 }
locations.filter((location) => {
return location.id == employee.location_id
});
console.log(locations);
this returns undefined when I'm trying to make it return { id: 1, name: 'N'}.
filter() function is not mutable - which means it returns a new array with the filtered objects and do not 'mutate' the original array - you must assign it to another variable - see demo below:
locations = [
{ id: 1, name: 'N'},
{ id: 2, name: 'P'}
]
employee = { location_id: 1 }
var result = locations.filter((location) => {
return location.id == employee.location_id
})
console.log(result);
You need a variable for the result of filtering with Array#filter
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
var locations = [
{ id: 1, name: 'N'},
{ id: 2, name: 'P'}
],
employee = { location_id: 1 },
result = locations.filter((location) => {
return location.id == employee.location_id
});
console.log(result);
You need to store the result of .filter(). It doesn't mutate the original array.
On a side note, you can shorten your callback function by removing the curly brackets and return statement.
locations = locations.filter(loc => loc.id == employee.location_id);

TypeScript - Take object out of array based on attribute value

My array looks like this:
array = [object {id: 1, value: "itemname"}, object {id: 2, value: "itemname"}, ...]
all my objects have the same attibutes, but with different values.
Is there an easy way I can use a WHERE statement for that array?
Take the object where object.id = var
or do I just need to loop over the entire array and check every item? My array has over a 100 entries, so I wanted to know if there was a more efficient way
Use Array.find:
let array = [
{ id: 1, value: "itemname" },
{ id: 2, value: "itemname" }
];
let item1 = array.find(i => i.id === 1);
Array.find at MDN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find
I'd use filter or reduce:
let array = [
{ id: 1, value: "itemname" },
{ id: 2, value: "itemname" }
];
let item1 = array.filter(item => item.id === 1)[0];
let item2 = array.reduce((prev, current) => prev || current.id === 1 ? current : null);
console.log(item1); // Object {id: 1, value: "itemname"}
console.log(item2); // Object {id: 1, value: "itemname"}
(code in playground)
If you care about iterating over the entire array then use some:
let item;
array.some(i => {
if (i.id === 1) {
item = i;
return true;
}
return false;
});
(code in playground)
You can search a certain value in array of objects using TypeScript dynamically if you need to search the value from all fields of the object without specifying column
var searchText = 'first';
let items = [
{ id: 1, name: "first", grade: "A" },
{ id: 2, name: "second", grade: "B" }
];
This below code will search for the value
var result = items.filter(item =>
Object.keys(item).some(k => item[k] != null &&
item[k].toString().toLowerCase()
.includes(searchText.toLowerCase()))
);
Same approach can be used to make a Search Filter Pipe in angularjs 4 using TypeScript
I had to declare the type to get it to work in typescript:
let someId = 1
array.find((i: { id: string; }) => i.id === someId)
You'll have to loop over the array, but if you make a hashmap to link each id to an index and save that, you only have to do it once, so you can reference any objeft after that directly:
var idReference = myArray.reduce(function( map, record, index ) {
map[ record.id ] = index;
return map;
}, {});
var objectWithId5 = myArray[ idReference["5"] ];
This does assume all ids are unique though.

Create new array from iterating JSON objects and getting only 1 of its inner array

See jsfiddle here: https://jsfiddle.net/remenyLx/2/
I have data that contains objects that each have an array of images. I want only the first image of each object.
var data1 = [
{
id: 1,
images: [
{ name: '1a' },
{ name: '1b' }
]
},
{
id: 2,
images: [
{ name: '2a' },
{ name: '2b' }
]
},
{
id: 3
},
{
id: 4,
images: []
}
];
var filtered = [];
var b = data1.forEach((element, index, array) => {
if(element.images && element.images.length)
filtered.push(element.images[0].name);
});
console.log(filtered);
The output needs to be flat:
['1a', '2a']
How can I make this prettier?
I'm not too familiar with JS map, reduce and filter and I think those would make my code more sensible; the forEach feels unnecessary.
First you can filter out elements without proper images property and then map it to new array:
const filtered = data1
.filter(e => e.images && e.images.length)
.map(e => e.images[0].name)
To do this in one loop you can use reduce function:
const filtered = data1.reduce((r, e) => {
if (e.images && e.images.length) {
r.push(e.images[0].name)
}
return r
}, [])
You can use reduce() to return this result.
var data1 = [{
id: 1,
images: [{
name: '1a'
}, {
name: '1b'
}]
}, {
id: 2,
images: [{
name: '2a'
}, {
name: '2b'
}]
}, {
id: 3
}, {
id: 4,
images: []
}];
var result = data1.reduce(function(r, e) {
if (e.hasOwnProperty('images') && e.images.length) r.push(e.images[0].name);
return r;
}, [])
console.log(result);
All answers are creating NEW arrays before projecting the final result : (filter and map creates a new array each) so basically it's creating twice.
Another approach is only to yield expected values :
Using iterator functions
function* foo(g)
{
for (let i = 0; i < g.length; i++)
{
if (g[i]['images'] && g[i]["images"].length)
yield g[i]['images'][0]["name"];
}
}
var iterator = foo(data1) ;
var result = iterator.next();
while (!result.done)
{
console.log(result.value)
result = iterator.next();
}
This will not create any additional array and only return the expected values !
However if you must return an array , rather than to do something with the actual values , then use other solutions suggested here.
https://jsfiddle.net/remenyLx/7/

How can I get a unique array based on object property using underscore

I have an array of objects and I want to get a new array from it that is unique based only on a single property, is there a simple way to achieve this?
Eg.
[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
Would result in 2 objects with name = bill removed once.
Use the uniq function
var destArray = _.uniq(sourceArray, function(x){
return x.name;
});
or single-line version
var destArray = _.uniq(sourceArray, x => x.name);
From the docs:
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.
In the above example, the function uses the objects name in order to determine uniqueness.
If you prefer to do things yourself without Lodash, and without getting verbose, try this uniq filter with optional uniq by property:
const uniqFilterAccordingToProp = function (prop) {
if (prop)
return (ele, i, arr) => arr.map(ele => ele[prop]).indexOf(ele[prop]) === i
else
return (ele, i, arr) => arr.indexOf(ele) === i
}
Then, use it like this:
const obj = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
obj.filter(uniqFilterAccordingToProp('abc'))
Or for plain arrays, just omit the parameter, while remembering to invoke:
[1,1,2].filter(uniqFilterAccordingToProp())
If you want to check all the properties then
lodash 4 comes with _.uniqWith(sourceArray, _.isEqual)
A better and quick approach
var table = [
{
a:1,
b:2
},
{
a:2,
b:3
},
{
a:1,
b:4
}
];
let result = [...new Set(table.map(item => item.a))];
document.write(JSON.stringify(result));
Found here
You can use the _.uniqBy function
var array = [ { id: 1, name: 'bob' }, { id: 2, name: 'bill' }, { id: 1, name: 'bill' },{ id: 2, name: 'bill' } ];
var filteredArray = _.uniqBy(array,function(x){ return x.id && x.name;});
console.log(filteredArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
In the above example, filtering is based on the uniqueness of combination of properties id & name.
if you have multiple properties for an object.
then to find unique array of objects based on specific properties, you could follow this method of combining properties inside _.uniqBy() method.
I was looking for a solution which didn't require a library, and put this together, so I thought I'd add it here. It may not be ideal, or working in all situations, but it's doing what I require, so could potentially help someone else:
const uniqueBy = (items, reducer, dupeCheck = [], currentResults = []) => {
if (!items || items.length === 0) return currentResults;
const thisValue = reducer(items[0]);
const resultsToPass = dupeCheck.indexOf(thisValue) === -1 ?
[...currentResults, items[0]] : currentResults;
return uniqueBy(
items.slice(1),
reducer,
[...dupeCheck, thisValue],
resultsToPass,
);
}
const testData = [
{text: 'hello', image: 'yes'},
{text: 'he'},
{text: 'hello'},
{text: 'hell'},
{text: 'hello'},
{text: 'hellop'},
];
const results = uniqueBy(
testData,
item => {
return item.text
},
)
console.dir(results)
In case you need pure JavaScript solution:
var uniqueProperties = {};
var notUniqueArray = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ];
for(var object in notUniqueArray){
uniqueProperties[notUniqueArray[object]['name']] = notUniqueArray[object]['id'];
}
var uniqiueArray = [];
for(var uniqueName in uniqueProperties){
uniqiueArray.push(
{id:uniqueProperties[uniqueName],name:uniqueName});
}
//uniqiueArray
unique array by id property with ES6:
arr.filter((a, i) => arr.findIndex(b => b.id === a.id) === i); // unique by id
replace b.id === a.id with the relevant comparison for your case

Categories

Resources