Need to make this array of objects function reusable in javaScript - javascript

In the map function... if the arrayOfObjects was not "obj.car" but was say "obj.animal" or obj.anything... I don't want to have to change that line for every array of objects I use the function on that has a different property name. Ultimately the function should take in an array of objects then return an array of values and check for duplicates then return unique array. Thanks in advance. Also I am new and I feel like I shouldn't be using two return statements within one function so any tips much appreciated.
const arrObj = [
{ car: "BMW" },
{ car: "Honda" },
{ car: "BMW" },
{ car: "BMW" },
];
const duplicates = (arrayOfObjects) => {
var finalArray = arrayOfObjects.map((obj) => {
return obj.car;
});
const uniqueSet = new Set(finalArray);
const uniqueArr = [...uniqueSet];
return uniqueArr;
};
console.log(duplicates(arrObj));

Have your duplicates function also accept a key, then use bracket notation to look up that key:
const arrObj = [
{ car: "BMW" },
{ car: "Honda" },
{ car: "BMW" },
{ car: "BMW" },
];
const duplicates = (arrayOfObjects, key) => {
var finalArray = arrayOfObjects.map((obj) => {
return obj[key];
});
const uniqueSet = new Set(finalArray);
const uniqueArr = [...uniqueSet];
return uniqueArr;
};
console.log(duplicates(arrObj, 'car'));

Related

Unstring an object property name javascript

I have an object similar to this:
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
I want to transfrorm every property name that is a string into a non-string one, like this:
const obj = {
id: 1,
name: {
english_us: "John",
english_uk: "John",
italian_eu: "Giovanni",
},
};
I can't modify the original object. I get it from an axios request.
You could use regex with stringify
let output = JSON.parse(JSON.stringify(obj).replace(/"(.*?)":.*?,?/g,
key=>key.replace(/\-/g, `_`)));
Output
console.log(JSON.stringify(output, null, 4));
/*
{
"id": 1,
"name": {
"english_us": "John",
"english_uk": "John",
"italian_eu": "Giovanni"
}
}*/
If you can copy the object, you could check this solution for declaring the attributes:
link
There are a few ways of achieving this. This example has a function that converts the key on every iteration of the name entries. A new names object is updated with these properties, and is later folded into a new object along with the existing properties of the original object.
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
const convert = (key) => key.replace('-', '_');
const updatedName = {};
for (const [key, value] of Object.entries(obj.name)) {
updatedName[convert(key)] = value;
}
const newObj = { ...obj, name: updatedName };
console.log(newObj);
You can convert object to JSON and convert back.
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
console.log(JSON.parse(JSON.stringify(obj)))
Two ways to clone the object and rename all keys from its name property
const obj = {
id: 1,
name: {
"english-us": "John",
"english-uk": "John",
"italian-eu": "Giovanni",
},
};
// clone obj
const myObj = window.structuredClone ?
structuredClone(obj) : JSON.parse(JSON.stringify(obj));
// rename all keys in myObj.name
Object.keys(myObj.name).forEach(key => {
myObj.name[key.replace(/\-/g, `_`)] = myObj.name[key];
delete myObj.name[key];
});
console.log(myObj.name.english_us);
// obj is untouched
console.log(obj.name[`english-us`]);
// myObj.name[`english-us`] does not exist
console.log(myObj.name[`english-us`]);
// alternative: clone and rename in one go
const myObjClone = {
...obj,
name: Object.fromEntries(
Object.entries(obj.name)
.reduce( (acc, [k, v]) =>
[ ...acc, [ k.replace(/\-/g, `_`), v ] ] , [] ) )
};
console.log(myObjClone.name.italian_eu);
// obj is untouched
console.log(obj.name[`italian-eu`]);
// myObjClone.name[`italian-eu`] does not exist
console.log(myObjClone.name[`italian-eu`]);

Best way to convert array to object [duplicate]

This question already has answers here:
How to convert an array into an object in javascript with mapped key-value pairs?
(4 answers)
Closed 10 months ago.
What is the best way to convert this
const items = [
{ name: "Leon", url: "../poeple" },
{ name: "Bmw", url: "../car" }
];
into this using javascript :
const result = {
Leon: "../poeple",
Bmw: "../car"
};
You could just reduce the array:
const items = [{
name: "Leon",
url: "../people"
},
{
name: "Bmw",
url: "../car"
}
];
const o = items.reduce((o, el) => {
o[el.name] = el.url;
return o;
}, {});
console.log(o)
The Array.prototype.reduce method is very flexible, and might be used to reduce an array to another entity:
The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
You could map the objects as entries and get an object from it.
const
items = [{ name: "Leon", url: "../poeple" }, { name: "Bmw", url: "../car" }],
result = Object.fromEntries(items.map(({ name, url }) => [name, url]));
console.log(result);
There are lots of different approaches as your can see. But if you're new to JavaScript maybe a simple loop over the array to create new keys and values in a new object would be easier to understand.
const items=[{name:"Leon",url:"../poeple"},{name:"Bmw",url:"../car"}];
const out = {};
for (const obj of items) {
out[obj.name] = obj.url;
}
console.log(out);
Another way (tested on your example):
function convertit (src) {
var dest = {}, i;
for (i = 0; i < src.length; i++) {
var record = src[i];
dest[record.name] = record.url;
}
return dest;
}
Try Like This
const items = [
{ name: "Leon", url: "../poeple" },
{ name: "Bmw", url: "../car" }
];
const newObj = Object.fromEntries(items.map(ele => [ele.name,ele.url]));
console.log(newObj);
Or You can create function like this
const items = [
{ name: "Leon", url: "../poeple" },
{ name: "Bmw", url: "../car" }
];
const convertArrayToObject = (array, key) => {
const initialValue = {};
return array.reduce((obj, item) => {
return {
...obj,
[item[key]]: item.url,
};
}, initialValue);
};
console.log(convertArrayToObject(items, "name"));

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

How to map matching property values into same object?

I'm mapping matching Objects into one where the ID property values match.
So far the reduce and map works fine for the ID and Fet properties.
But now I want to map the Name property to each new mapped object. I did try the following but this creates a new Object separate to the others with the Name values.
How can I map matching property values to an object?
https://jsfiddle.net/brianVarley/zs8xadht/
This is what I tried in order to get the Name mapping:
const arr = [{ ID:12, Fet: "Donuts", Name: "DD" } , { ID: 12, Fet: "Cake", Name: "DD" }, { ID: 13, Fet: "Lemon", Name: "CC"}] ;
const grouped = arr.reduce((a,v) => {
if( !(v.ID in a) ) a[v.ID] = [];
a.Name = v.Name
a[v.ID].push(v.Fet);
return a;
},{});
var newArrayOfReducedObjects = Object.keys(grouped).map(key => {
return { ID: key, Name: key, Fet: grouped[key] };
});
console.log(newArrayOfReducedObjects);
I think you should use generic group by function which you can use with various keys for an array of objects.
var customGroupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
Then you can call this function for any key:
customGroupBy (arr,"ID")
customGroupBy (arr,"Name")
The last call above will result in (JSONified)
"{"DD":[{"ID":12,"Fet":"Donuts","Name":"DD"},{"ID":12,"Fet":"Cake","Name":"DD"}],"CC":[{"ID":13,"Fet":"Lemon","Name":"CC"}]}"

Is there a method to split an array of objects into groups?

Suppose I have an array of objects with some sort of groupable key:
var people = [
{ 'name':'Alice', 'gender': 'female' },
{ 'name':'Bob', 'gender': 'male' },
{ 'name':'Jeremy', 'gender': 'male' },
{ 'name':'Jess', 'gender': 'female' },
{ 'name':'Seymour', 'gender': 'female' },
];
Is there a (native) function/method that can be applied to the array to 'unzip' the array into two arrays, like so:
boysAndGirls = people.[**something**]('gender');
That could result in:
{
'male': [ ... ],
'female': [ ... ]
}
or even:
[
[ {Bob, ...}, {Jeremy, ...}, {Seymour, ...} ], // 'males' array
[ {Alice, ...}, {Jess, ...} ] // 'female' array
]
I could write this algorithm myself, but I really just want to know if there is a native array method -- or one that might exist in another language that could be polyfilled in?
const groupByAge = users.reduce((p,c) =>{
const genKey = Math.floor(c.age/10);
const key = `${genKey}0- ${genKey}9`;
if(!p[key]){
p[key] =[];
}
p[key].push(c);
return p;
}, {})
console.log(groupByAge);
There is no such method in JavaScript. Ruby has it in Enumerator#group_by:
people.group_by { |person| person['gender'] }
and it is easy enough to write in JavaScript as well. In fact, some libraries have it already, e.g. Lodash.
_.groupBy(people, function(person) {
return person['gender'];
});
If you write it yourself, you can customise it a bit:
function groupByProp(array, prop) {
var result = {};
array.forEach(function(item) {
var val = item[prop];
if (!result[val]) result[val] = [item];
else result[val].push(item);
});
return result;
}
groupByProp(people, 'gender');
There is not a native Javascript function for this but you can use the following code:
var originalArray = [1,2,3,4,5,6,7,8,9];
var splitArray = function (arr, size) {
var arr2 = arr.slice(0),
arrays = [];
while (arr2.length > 0) {
arrays.push(arr2.splice(0, size));
}
return arrays;
}
splitArrays = splitArray(originalArray, 2);
console.log(splitArrays);
The nearest thing I can think of off the top of my head for a native solution is to use reduce. It's not as simple as what you are looking for but it works:
var boysAndGirls = people.reduce(function(obj, item) {
obj[item.gender].push(item.name);
return obj;
}, {male: [], female: []});

Categories

Resources