How to create function to create array of keys? [closed] - javascript

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Suppose I have an array of users:
const users =[
{
id:1,
name:'bob',
},
{
id:2,
name:'sally',
},
{
id:3,
name:'bob',
age:30,
}
];
Now I want to extract the keys by either name,id or age(example for name):
const arrangeByName = arrangeBy('name');
arrangeByName(users);
So the result would be:
['bob','sally'];
My arrangeBy function looks like this:
const go = A => key => {
return A.map(a => a.key);
};
export default go;
But when I run this I get:
A.map is not a function
How can I write a function that can extract keys in an array? Also note that any duplicates are not created in the output.

Since you want to exclude objects for which the given key property is not present, and want to exclude duplicates, things become a little more complex.
This solution filters out the objects for which the property is not present, and uses a Set to avoid duplicates:
const arrangeBy = key => A => [...A.reduce((s, v) => key in v ? s.add(v[key]) : s, new Set())];
Complete snippet:
const users = [{
id: 1,
name: 'bob',
}, {
id: 2,
name: 'sally',
}, {
id: 3,
name: 'bob',
age: 30,
}];
const arrangeBy = key => A => [...A.reduce((s, v) => key in v ? s.add(v[key]) : s, new Set())];
const arrangeByName = arrangeBy('name');
const arrangeByAge = arrangeBy('age');
console.log(arrangeByName(users));
console.log(arrangeByAge(users));

I see two issues. One, your arguments are in the wrong order as it seems you want arrangeBy to accept a key and return a function that accepts users. Second, a.key will try to access a property called "key" on the object, which I doubt is what you are trying to do - you will instead want to do a[key]
// get values of key, removing duplicates
const arrangeBy = key => arr =>
[...arr.reduce((set, el) => set.add(el[key]), new Set)]
const arrangeByName = arrangeBy('name')
const arrangeById = arrangeBy('id')
const users = [{id: 1, name: 'bob'}, {id: 2, name: 'sally'}, {id: 3, name: 'bob'}]
console.log(arrangeByName(users))
console.log(arrangeById(users))

You can create Array.prototype.arrangeBy:
Array.prototype.arrangeBy = function(key) {
const array = this
.filter(el => !!el[key])
.map(el => el[key])
return [...new Set(array)]
}
const users = [{
id: 1,
name: 'bob'
}, {
id: 2,
name: 'sally'
},
{
id: 3,
name: 'bob',
age: 30
}
]
console.log(users.arrangeBy('id'))
console.log(users.arrangeBy('name'))
console.log(users.arrangeBy('age'))

function arangeByKey(key) {
return function (arr) {
return arr.map(item => item[key]);
};
}
const arangeByName = arangeByKey('name');
const arrangeById = arangeByKey('id');
console.log(arangeByName(users));
console.log(arrangeById(users));
// If array contains unique element
console.log([... new Set(arangeByName(users))]);

Related

How to extract numbers from an array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 24 days ago.
Improve this question
So basically I have an array of ids and I want to return only a simple array which I want to look like this
*[1,2,3]*
instead of
*[0:[1] , 1:[2]]*
Is there any way to do it
Code
const usersWhoHavePurchasedYourCourses = usersWhoHaveTokens.filter(
(user1: any) => {
return user1.tokens
?.map((token: any) => parseInt(token.course_id))
.includes(user.courses?.map((course: any) => course.id));
});
The output looks like this
output
As I said I don`t want to return this kind of output.
Edit
In attempting to reverse-engineer your logic, wouldn't you want to filter by checking if a user has at least one course? I recommend using Array.prototype.some as your filter result.
const user = { courses: [{ id: 1 }, { id: 2 }] };
const usersWhoHaveTokens = [
{ id: 1, tokens: [{ course_id: '1' }] },
{ id: 2, tokens: [{ course_id: '2' }] },
{ id: 3, tokens: [{ course_id: '3' }] },
];
// Compute the set, for faster processing
const userCourseIds = new Set(user.courses.map((course) => course.id));
const usersWhoHavePurchasedYourCourses = usersWhoHaveTokens
.filter(({ tokens }) => tokens
.some((token) => userCourseIds.has(parseInt(token.course_id))))
.map(({ id }) => id);
console.log(usersWhoHavePurchasedYourCourses); // [1, 2]
Original response
If you object is an 'object' type, you will need to transform it into an array, and then flatten it.
const
obj = { 0: [1], 1: [2] },
arr = Object.values(obj).flat();
console.log(JSON.stringify(arr)); // [1, 2]
If you want to preserve indices:
const
obj = { 1: [2], 5: [6] },
arr = Object.entries(obj).reduce((acc, [index, value]) => {
acc[+index] = value;
return acc;
}, []).map(([value]) => value);
console.log(JSON.stringify(arr)); // [null, 2, null, null, null, 6]

Generate Children element based on number of keys in object [duplicate]

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 3 years ago.
I have my object that is stored in variable val.Main.widgets. I also have variable that functions as a data tree. What I need is to generate as many children elements as there are keys in my object that is stored in val.Main.widgets. If I console log this: console.log(Object.keys(val.Main.widgets).length;, it returns 8 so in this case I need to generate 8 children elements.
I am guessing I need some sort of cycle, but I really dont know where to start, hence why I am asking here.
Here is my object:
And here is my tree variable:
const tileTree = [
{
name: val.Main.name,
children: [
{
name: val.Main.widgets['E1EV7'].name,
},
{
name: val.Main.widgets['E70ZT'].name,
},
],
},
];
Thank you for any advice.
You do not need lodash for this. You want to use Array.map on the result of Object.keys.
const content = val.Main.widgets;
const keys = Object.keys(content);
const children = keys.map(key => content[key]);
Then in your tileTree you simply set children to children.
const tileTree = [
{
name: val.Main.name,
children,
},
];
This will give you all the properties of the val.Main.widgets object. If you only want specific ones, you can destructure them in your map function.
...
// Suppose we only want 'name'.
const children = keys.map(key => {
const { name } = content[key];
return { name };
});
...
You can use
Object.keys(val.Main.widgets).map(widgetKey => {
const widget = val.Main.widgets[widgetKey]
return (
<div key={widgetKey}>
<h1>This is widget : {widget.name}</h1>
</div>
)
}
const tileTree = [
{
name: 'test',
children: [
{
name: 'test1'
},
{
name: 'test2'
},
{
name: 'test3'
},
{
name: 'test4'
},
{
name: 'test5'
},
{
name: 'test6'
}
],
},
];
const createLi = (arr) => {
for (let i = 0; i < arr[0].children.length; i += 1) {
let li = document.createElement("li");
let ol = document.getElementById('list');
li.innerHTML = arr[0].children[i].name;
ol.appendChild(li);
}
}
createLi(tileTree);
https://jsfiddle.net/os20wdLh/
Object.keys is a function that returns an array. The array has a foreach method
var lunch = {
sandwich: 'ham',
snack: 'chips',
drink: 'soda',
desert: 'cookie',
guests: 3,
alcohol: false,
};
Object.keys(lunch).forEach(function (item) {
console.log(item); // key
console.log(lunch[item]); // value
});
Other way is by using lodash module from npm or yarn. example where _ is the lodash module:
_.times(8, i => {
schedule.push({
date: moment()
.add(i, "days")
.format("YYYY-MM-DD"),
times: [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
});
});
You can replace the 8 with your .length code.

Joining two arrays of JSON objects like an SQL join using functional programming

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

Javascript - How to filter object values with search input and get its key based on that?

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

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