I want to get result of all strength properties in the array for a specific name.
For example, I want to get strength for pachio & hunter only. The expected result should be,
['cool kids', 'suck bloods']
I only know how to filter one value.
const array = [{
name: 'pachio',
strength: 'cool kids'
}, {
name: 'hunter',
strength: 'suck bloods'
}, {
name: 'chloyi',
strength: 'cute'
}]
const result = array.filter(function(getName) {
return getName.name == 'pachio'; /*This_need_to_be_fix*/
});
const result2 = result.map((getStrength) => getStrength.strength);
console.log(result2) /*cool kids*/
You can also combine two methods
const array = [{
name: 'pachio',
strength: 'cool kids'
},
{
name: 'hunter',
strength: 'suck bloods'
},
{
name: 'chloyi',
strength: 'cute'
},
]
let ar = ['pachio', 'hunter']
let data = array.filter(el => ar.includes(el.name)).map(ob => ob.strength)
console.log(data)
You're already using the correct method, filter(), you simply need to add another condition to the function to also allow the name property value to be hunter:
const array = [{
name: 'pachio',
strength: 'cool kids'
}, {
name: 'hunter',
strength: 'suck bloods'
}, {
name: 'chloyi',
strength: 'cute'
}]
const result = array.filter(o => o.name == 'pachio' || o.name == 'hunter');
const result2 = result.map(o => o.strength);
console.log(result2)
If the list of allowed names gets longer, then you can use an array to contain them to keep the logic more clear:
const targetNames = ['pachio', 'hunter'];
const result = array.filter(o => targetNames.includes(o.name));
You can also use a second search array, if you want it to be more dynamic, e.g from an input.
const searchBy = ['pachio', 'hunter']
const array = [{
name: 'pachio',
strength: 'cool kids'
}, {
name: 'hunter',
strength: 'suck bloods'
}, {
name: 'chloyi',
strength: 'cute'
}]
const result = array.filter(o => searchBy.includes(o.name));
const result2 = result.map(o => o.strength);
console.log(result2)
This solution uses .filter like you and Rory have mentioned but adds .includes to check for the match.
Before answering, the next time you ask, please arrange the code with quotation marks where necessary.
A filter returns you all the values that match the condition,
According to what you are asking for, you want anyone who is different from = "chloyi"
so...
const array = [
{
name: "pachio",
strength: "cool kids"
},
{
name: "hunter",
strength: "suck bloods"
},
{
name: "chloyi",
strength: "cute"
}
]
const result = array.filter(function (getName) {
return getName.name !== 'chloyi';
});
const result2 = result.map((getStrength) => getStrength.strength);
console.log(result2)
Related
I am writing some Google Apps Script to get each Google Group and list it's members then output it to a Google Sheet. Currently, I am grabbing each group and email address and pushing it to the memberArr, however I then want to 'merge' the relevant information.
So if for example, I have X Groups and Group 1 has 4 members (Foo, Bar, Baz and Quux) - Currently, it will output as
[ [ 'Group 1', 'Foo' ],
[ 'Group 1', 'Bar' ],
[ 'Group 1', 'Baz' ],
[ 'Group 1', 'Quux' ] ]
But I want to have it output as [Group 1, Foo, Bar, Baz, Quux].
That is to say, merge the contents of the memberArr where there is a common Group
Here is my code so far:
function getAllGroupsTEST() {
const groupArr = [];
let gPageToken;
let gPage;
do {
gPage = AdminDirectory.Groups.list({
customer: "my_customer",
maxResults: 100,
gPageToken
});
const groups = gPage.groups;
if (groups) {
groups.forEach(({email}) => {
const groupEmail = email;
groupArr.push(groupEmail);
});
}
gPageToken = gPage.nextPageToken;
} while (gPageToken);
console.log(`LOGGING GROUPS:\n\n${groupArr}`);
const memberArr = [];
let mPageToken;
let mPage;
groupArr.forEach(group => {
mPage = AdminDirectory.Members.list(group,{
customer: "my_customer",
maxResults: 500,
mPageToken
})
const members = mPage.members;
if (members) {
// console.log(`LOGGING ${members.length} MEMBERS FOR ${group}\n\n${members}`)
members.forEach(member => {
// console.log(`MEMBER: ${member.email} IS IN GROUP ${group}`)
memberArr.push([group, member.email])
})
}
})
// console.log(`COUNTED ${groupArr.length} GROUPS`)
// console.log(memberArr)
}
Any help would be greatly appreciated!
Edit: Updated to show the memberArr as is rather than in a table format.
I'd propose to convert the array in the object and then back to the array this way:
var arr = [
['group1','a'],
['group1','b'],
['group2','c'],
['group2','d'],
['group3','e']
]
var obj = {}
for (var a of arr) {
try { obj[a[0]].push(a[1]) }
catch(e) { obj[a[0]] = [a[1]] }
}
console.log(obj);
var new_arr = [];
for (var group in obj) {
new_arr.push([group, ...obj[group]])
}
console.log(new_arr);
Output:
[ [ 'group1', 'a', 'b' ], [ 'group2', 'c', 'd' ], [ 'group3', 'e' ] ]
I like #YuriKhristich solution. However, I still want to post this code showing how you could make a few minor changes to your existing code to build your required data structure.
We start by initializing a list with the group email. Next we append all the member emails to the list. And finally we push the completed list to memberArr. The advantage is that this builds the required data format while the data is read rather than trying to rework it afterward.
let list = [group]; // <-- ADD
if (members) {
members.forEach(member => {
// memberArr.push([group, member.email]) <-- REMOVE
list.push(member.email); // <-- ADD
})
memberArr.push(list); // <-- ADD
}
})
// Simulated Google Groups data
var gPage = {
groups: [
{id: 1, name: "Group 1", email: "group1#emal.com" },
{id: 2, name: "Group 2", email: "group2#emal.com" },
{id: 3, name: "Group 3", email: "group3#emal.com" }
]
};
var mPage = {
members: [
{id: 1, role: "admin", email: "member1#email.com" },
{id: 2, role: "admin", email: "member2#email.com" },
{id: 3, role: "admin", email: "member3#email.com" },
{id: 4, role: "admin", email: "member4#email.com" },
{id: 5, role: "admin", email: "member5#email.com" }
]
};
function getAllGroupsTEST() {
const groupArr = [];
let gPageToken;
//let gPage;
do {
/* useing fake data
gPage = AdminDirectory.Groups.list({
customer: "my_customer",
maxResults: 100,
gPageToken
});
*/
const groups = gPage.groups;
if (groups) {
groups.forEach(({email}) => {
const groupEmail = email;
groupArr.push(groupEmail);
});
}
gPageToken = gPage.nextPageToken;
} while (gPageToken);
const memberArr = [];
let mPageToken;
//let mPage;
groupArr.forEach(group => {
/* using fake data
mPage = AdminDirectory.Members.list(group,{
customer: "my_customer",
maxResults: 500,
mPageToken
})
*/
const members = mPage.members;
let list = [group];
if (members) {
members.forEach(member => {
// memberArr.push([group, member.email])
list.push(member.email);
})
memberArr.push(list);
}
})
return memberArr;
}
console.log( getAllGroupsTEST() );
You can implement this easy function for every group you want to filter
Take into account that this will eliminate every duplicate of the array.
const dataToFiler = [['Group 1', 'Foo'],
['Group 1', 'Bar'],
['Group 1', 'Baz'],
['Group 1', 'Quux']]
const filterRD = (arr) => {
return [...new Set(arr.flat())]
}
console.log(filterRD(dataToFiler))
Documentation
Set
Array.prototype.flat()
Consider, I have the following two arrays of objects:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
What I want to do is determine which of the bookings in the second array are new and which are existing. Any bookingId that is in both arrays is existing. Any bookingID that is in the second array but not the first is new. So, the result of the solution should be an array as follows:
[ { bookingId: -2, existing: true, name: 'name1' },
{ bookingId: -3, existing: false, name: 'name1' },
{ bookingId: -1, existing: true, name: 'namex' } ]
I have a solution (which I'll post as an answer), but I think there's probably a more efficient way of doing it. Good luck.
If you want a non-R answer: you can use a simple map to iterate over the data, compare the booking ids in both arrays (with some), and return a new array of objects.
const existingAndArchivedBookings = [{booking_id:-2},{booking_id:-1},{booking_id:999}];
const newAndExistingBookings = [{bookingId:-2, name: "name1"},{bookingId:-3, name: "name1"},{bookingId:-1, name: "namex"}];
function testBookings(arr1, arr2) {
return arr2.map(({ bookingId, name }) => {
const existing = arr1.some(obj => obj.booking_id === bookingId);
return { bookingId, existing, name };
});
}
const out = testBookings(existingAndArchivedBookings, newAndExistingBookings);
console.log(out);
You can greatly simplify it using Array.prototype.reduce to form the result of the comparisons between the 2 arrays and Array.prototype.findIndex to test whether the object in the second array is present in the first array:
const existingAndArchivedBookings =
[
{"booking_id":-2},
{"booking_id":-1},
{"booking_id":999}
]
const newAndExistingBookings =
[
{bookingId:-2, name: "name1"},
{bookingId:-3, name: "name1"},
{bookingId:-1, name: "namex"}
]
const res = newAndExistingBookings.reduce((acc, ele) => {
const idx = existingAndArchivedBookings.findIndex(b => b.booking_id === ele.bookingId);
let existing = false;
if(idx >=0 ){
existing = true;
}
return acc.concat({bookingId : `${ele.bookingId}`, existing: `${existing}`, name: `${ele.name}`});
}, []);
console.log(res);
Here's what I came up with, which seems a bit long winded
const R = require('ramda')
const existingAndArchivedBookings = [{"booking_id":-2},{"booking_id":-1},{"booking_id":999}]
const newAndExistingBookings = [{bookingId:-2, name: "name1"}, {bookingId:-3, name: "name1"}, {bookingId:-1, name: "namex"}]
const existingAndArchivedKeys = existingAndArchivedBookings.map(value => value.booking_id)
const newAndExistingKeys = newAndExistingBookings.map(value => value.bookingId)
const existingKeys = existingAndArchivedKeys.filter(key => newAndExistingKeys.includes(key))
const newKeys = newAndExistingKeys.filter(key => !existingAndArchivedKeys.includes(key))
const existingBookingIds = existingKeys.map(key => {
return {bookingId: key, existing: true}
})
const newBookingIds = newKeys.map(key => {
return {bookingId: key, existing: false}
})
const allArray = R.concat(newAndExistingBookings, R.concat(existingBookingIds, newBookingIds))
console.log(R.values(R.reduceBy(R.mergeLeft, {}, R.prop('bookingId'), allArray)))
I know this question was answered before multiple times.
but i didn't find any solution that helped me out.
I got an array of objects with a Name property. I only want to get the objects with the same name.
How my Array looks like:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
so I only want to get:
[
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
]
I hope someone can help me out :)
For an O(N) solution, first reduce the array into an object that counts the number of occurrences of each name, and then filter the input by the occurrence count being 2:
const arr = [
{
Name: 'test',
coolProperty: 'yeahCool1'
},
{
Name: 'test1',
coolProperty: 'yeahCool2'
},
{
Name: 'test2',
coolProperty: 'yeahCool3'
},
{
Name: 'test3',
coolProperty: 'yeahCool4'
},
{
Name: 'test',
coolProperty: 'yeahCool5'
}
];
const counts = arr.reduce((a, { Name }) => {
a[Name] = (a[Name] || 0) + 1;
return a;
}, {});
console.log(arr.filter(({ Name }) => counts[Name] === 2));
You could use reduce() and filter() method to get the required result.
Using filter() method you need to check if length is greater than 2 then need it will be push in new array inside of reduce() method
DEMO
const arr =[{"Name":"test","coolProperty":"yeahCool1"},{"Name":"test1","coolProperty":"yeahCool2"},{"Name":"test2","coolProperty":"yeahCool3"},{"Name":"test3","coolProperty":"yeahCool4"},{"Name":"test","coolProperty":"yeahCool5"}];
let getCount = (name)=>{
return arr.filter(o => o.Name == name).length;
}
console.log(arr.reduce((r,item) => {
let len = getCount(item.Name);
return r.concat(len>1?item:[]);
}, []));
I see that you have already got an answer. So I thought of adding another way using map.
var counts = {};
var repeats = {};
arr.map(i => {
counts[i['Name']] = (counts[i['Name']] || []);
counts[i['Name']].push(i);
if (counts[i['Name']].length > 1) {
repeats[i['Name']] = counts[i['Name']];
}
});
console.log(repeats);
Not the best solution considering the performance. Just wanted to add an alternative method.
Hope it helps!!
const obj ={
1: {name:"josh",age:2, symbol: "abc", id: 1},
2: {name:"mike",age:4, symbol: "efg", id: 2}
}
const search = (input) => {
return Object.values(obj).filter(item => {
return item.name.includes(input)
})
}
search("mi")
// returns: [ { name: 'mike', age: 4, symbol: 'efg', id: 2 } ]
How can I access the found objects id (id:1)
How can I get the found objects key (1: ...)
I am trying to find 1 and 2 of the object inside my array which matched my search input (see function)! In my filter I search for an object inside my array and see if one of those objects matches (or not) my search input. Then based on that I want to find the id of THAT object and its key
Thanks!
You had it right, except when you used Object.values you lost the object keys, check demo below
const obj ={
1: {name:"josh",age:2, symbol: "abc", id: 1},
2: {name:"mike",age:4, symbol: "efg", id: 2}
}
const search = (input) => {
return Object.keys(obj).filter(key => {
return obj[key].name.includes(input)
})
.map(foundKey => ({...obj[foundKey], key: foundKey }))
}
const result = search("mi")
console.log(result)
Change the search for this:
const search = input => Object.values(obj).findIndex(item => item.name.includes(input));
Your Search:
const index = search('mike');
Your ID:
const id = Object.keys(obj)[index];
Your Item:
const item = obj[id];
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