Javascript map an array to a new one with defined keys - javascript

what i need is to transform this Array
[
0: {id: 1},
1: {id: 2}
]
to
[
1: {id: 1},
2: {id: 2}
]
Just switching keys I suppose, Im trying to use .map but all i can change are the values not the keys

I think you can solve it easily enough with reduce
It starts with an empty array, and during each iteration 1 item is added, at the index of the items id field.
This will give you an array with a length that might not be what you have expected, so I would suggest to look a bit deeper into your requirements.
var arr = [
{id: 1},
{id: 2}
];
var result = arr.reduce( (container, item) => {
container[item.id] = item;
return container;
}, [] );
console.log( result[1] );
console.log( result[2] );
console.log( result );
You could always make it an object with the correct keys, with pretty much the same syntax
var arr = [
{id: 1},
{id: 2}
];
var result = arr.reduce( (container, item) => {
container[item.id] = item;
return container;
}, {} );
console.log( result[1] );
console.log( result[2] );
console.log( result );
And important thing to note, is that with the array, you have an undefined value at position 0, the object version doesn't have it. It would make more sense to use the object version, and not the array. As mentioned in the comments, it's not a very good idea to have gaps in your array.

Related

Given two array create another one with only different element

I have two array:
for example:
arraySelectedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
arraySavedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
now I need to check if there is some item in arraySavedItems that is not present in arraySelectedItems, and in this case I'll go to populate another array called arrayDeletedItems.
If the two arrays have the same items I don't need to populate the arrayDeletedItems.
So I have tried with this code:
arraySavedItems.filter((itemSaved) => !arraySelectedItems.find((itemSel) => {
if (itemSaved.id !== itemSel.id) {
arrayDeletedItems.push(itemSaved)
}
}
))
So with this data:
arraySelectedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
arraySavedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
I'll expect that arrayDeletedItems will be:
arrayDeletedItems = []
Instead whit this data for example:
arraySelectedItems = [{id: 1, name: "item1"}]
arraySavedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
I'll expect that arrayDeletedItems will be:
arrayDeletedItems = [{id: 2, name: "item2"}]
With my code I receive and arrayDeletedItems that has the all values:
arrayDeletedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}]
Consider this generic function:
function difference(a, b, keyFn) {
let keys = new Set(a.map(keyFn))
return b.filter(obj => !keys.has(keyFn(obj)))
}
//
selectedItems = [{id: 1, name: "item1"}, {id:4}]
savedItems = [{id: 1, name: "item1"}, {id: 2, name: "item2"}, {id:3}, {id:4}]
result = difference(selectedItems, savedItems, obj => obj.id)
console.log(result)
You can use the .includes() method on an array to check whether a value is contained in it (see the documentation for more information).
Now we can just filter the array of saved items to find only ones that aren't contained by the selected items array.
arrayDeletedItems = arraySavedItems.filter((itemSaved) =>
!arraySelectedItems.includes(itemSaved)
)
As #owenizedd points out in the comments, this only works for primitive data types where a shallow equality check is sufficient. A more robust approach can be used with the .reduce() method and a custom equality check. For example, lodash's isEqual() does a deep comparison for equality. You would have to import the module for this. Unfortunately there is no native deep equality check in JavaScript currently (workarounds like JSON.stringify() to then compare the string representations have various downsides).
arrayDeletedItems = arraySavedItems.filter((itemSaved) =>
!arraySelectedItems.reduce((previous, current) =>
previous || _.isEqual(current, itemSaved)
)
)
Note that passing previous as the first argument to the 'or' operator (||) means we can benefit from lazy evaluation - once a hit has been found, the second half of the statement does not need to be evaluated any more.
To solve this problem, since we have id we can utilize it.
You need a key that is unique. so id commonly known will have unique value.
So my approach, find items that is not exist in B array but in A array, and find items that exist in B but not in A array.
This approach not be the fastest, but the findDiff is reusable.
const a = [....];
const b = [....];
const findDiff = (source, target) => {
return source.filter((sourceItem, index) => {
const isInTarget = target.findIndex(targetItem => targetItem.id === sourceItem.id)
return isInTarget === -1
})
}
const difference = findDiff(a,b).concat(findDiff(b,a)); //result

How i can trasform an object in an array of object?

I have this object
{
Bamboo: 7,
Eucalipto: 1,
Frassino: 2,
Ulivo: 1
}
I want to trasform this object in an array of object
[
{
plantName: Bamboo,
quantity: 7
},
{
plantName: Eucalipto,
quantity: 1
},
{
plantName: Frassino,
quantity: 2
},
{
plantName: Ulivo,
quantity: 1
},
]
What have you tried so far? Here's what I might do.
const dataObject = { Bamboo: 7, Eucalipto: 1, Frassino: 2, Ulivo: 1 };
const dataArray = Object.keys( dataObject ).map( ( key ) => {
return { 'plantName': key, 'quantity': dataObject[key] };
} );
console.log( dataArray );
You can map over the entries of the object, creating a new object with each key-value pair.
let obj = { Bamboo: 7, Eucalipto: 1, Frassino: 2, Ulivo: 1 };
let res = Object.entries(obj).map(([plantName,quantity])=>({plantName, quantity}));
console.log(res);
As you can see there are many different ways of doing this. But here are the basic steps as I learned them when I was starting out.
Create an array.
Iterate over the object.
Create a new object, and assign the key of the input object to "plantName", and the value of the input object to "quantity".
Add that new object to an array.
Here's an old-school way of achieving this:
const obj = { Bamboo: 7, Eucalipto: 1, Frassino: 2, Ulivo: 1 };
// Create an array
const arr = [];
// Iterate over the object
for (const key in obj) {
// Create a new object assigning the key
// to `plantName`, and the value to `quantity`
const newObj = {
plantName: key,
quantity: obj[key]
};
// Add the new object to the array
arr.push(newObj);
}
// Et voila!
console.log(arr);
Once you understand the basic concepts then you can start to introduce more complex methods like Object.entries, and map, but if you're just starting out with JavaScript this is probably more than enough to help you understand the process.

How to get array of all keys which contain certain substring from dictionary array in JS?

How can I get an array of all keys which contain certain substring from dictionary array in JS? I tried to use reduce and map and filter, but don't know how to use those for this particular problem...
Input
[{id: 0, hello: 1}, {id: 1, world: 2}, {id: 2, bye: 3}]
Expected output (Get all keys with substring 'l')
['hello', 'world']
The .reduce method is great for this.
Here, we get the keys for each object in the array, and if a key contains the desired substring, we push it to the array that is being returned from each iteration of reduce.
const input =[
{id: 0, hello: 1}, {id: 1, world: 2}, {id: 2, bye: 3}
];
console.log(getKeysWithSubstring(input, "l"));
function getKeysWithSubstring(arrayOfObjs, needle){
return arrayOfObjs.reduce( (previousLoopOutput, currentObj) => {
// Renaming the output array for clarity
const thisLoopOutput = previousLoopOutput;
Object.keys(currentObj).forEach(haystack => {
// It's possible that many keys in the same object will be pushed
if(haystack.includes(needle)){
thisLoopOutput.push(haystack);
}
});
return thisLoopOutput;
}, []); // First time through loop, `previousLoopOutput` argument will be `[]`
}

Add key value to all objects in array from another with JavaScript

I wanted to add a key:value parameter to all the objects in an array from another array
eg:
var arrOfObj = [{id: 001, date:'22/05/2020', Actor:'jane'},
{id: 002, date:'02/03/2020', Actor:'alice'},
{id: 003, date:'11/06/2020', Actor:'jean'},
{id: 004, date:'20/01/2020', Actor:'yann'}];
var arrayScore = [44,2,3,5];
I want add for every objects a key:value parameter from arrayScore, like :
var arrOfObj = [{id: 001, date:'22/05/2020', Actor:'jane', score:44},
{id: 002, date:'02/03/2020', Actor:'alice', score:2},
{id: 003, date:'11/06/2020', Actor:'jean', score:3},
{id: 004, date:'20/01/2020', Actor:'yann', score:5}];
I tried this code:
var result = arrOfObj.map(function(el) {
var o = Object.assign({}, el);
o.score = arrayScore;
return o;
});
console.log(result);
but arrOfObj add all values from arrayScore for every object!!
How can I change this please??
Thank you for your HELP!
You can use Array.map to create the new array including the user scores, I would also take note of TJCrowders's point about the Ids.
var arrOfObj = [{id: 1, date:'22/05/2020', Actor:'jane'},
{id: 2, date:'02/03/2020', Actor:'alice'},
{id: 3, date:'11/06/2020', Actor:'jean'},
{id: 4, date:'20/01/2020', Actor:'yann'}];
var arrayScore = [44,2,3,5];
const result = arrOfObj.map((el, index) => ({...el, score: arrayScore[index] }));
console.log("Result with scores:", result);
Since you do not need a new array of objects, but only need to add the properties to the objects in the array, you can use the array method forEach instead of map.
If we pass two parameters to the callback provided to forEach, the second parameter will receive the index of the array element we are iterating over. This allows us to assign the corresponding value from the arrayScore array.
This should work
arrOfObj.forEach((o, i) => {
o.score = arrayScore[i];
});
Cheers!

How do I get an object parameter by its id?

I need to detect an object in an array with its Id.
My first array looks like that:
{ [id: 9, name: 'abc'], [id: 2, name 'def'], [id: 40, name: 'gh'] } (Id & name),
while that other array is:
{ [class: 'physics', Tid: 9], [class: 'computer science', Tid: 9], [class: 'Biology', Tid: 40] }.
I need to match the parameter "name" from the first array by its ID to its "class" (for example, "physics" relates to Tid=9 which is "abc" and "Biology" relates to Tid=40 which is "gh").
How can I elegantly do so without changing the way the data comes? (It comes from a database with ASP.NET web service in JSON)
You could use $http.get() which has success and error callback functions, which returns a promise object. Using this, you can setup a condition to map the id and get your desired result.
Something like this.
var myObject1 = {};
var myArray1 = [];
var myObject2 = {};
var myArray2 = [];
$http.get('json-file')
.success(function(data)) {
myObject1.myArray1 = data;
}
$http.get('json-file')
.success(function(data)) {
myObject2.myArray2 = data;
}
/* inside a loop if required */
if (myObject1.myArray1[index].id == myObject2.myArray2[index].Tid) {
/* perform logic */
}
This code would be present inside a service or a controller.
Haven't tested it so unsure of the syntax but promise objects are the way to go.
Hope this helps.
This returns an array of arrays. Each array in the array contains two objects matched by id === Tid. As far as I can tell that's what you want.
(Note that I think you provided broken sample arrays, I adjusted and scrambled the numbers around so you could see it work more clearly).
var arr1 = [ {id: 9, name: 'abc'}, {id: 2, name: 'def'}, {id: 40, name: 'gh'} ];
var arr2 = [ {class: 'physics', Tid: 2}, {class: 'computer science', Tid: 40}, {class: 'Biology', Tid: 9} ];
var arrFinal = arr1.map ( function ( d ) {
var matched = arr2.find ( function ( obj ) {
return obj.Tid === d.id;
} );
return [ d, matched ];
} );
If you iterate arrFinal you'll see it contains the matched objects.

Categories