Add key value to all objects in array from another with JavaScript - 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!

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

JavaScript Replacing Object in Array with ID Number

So I have a series of objects that are pulled from an API and inputted into an array, something like such:
array = [
{id: 0, name: "First", relationship: "Friend"},
{id: 1, name: "Second", relationship: "Friend"}
]
The user is allowed to add and remove objects to the list freely (they will appear within a Vue.JS DataTable), and said user is allowed a maximum of 4 objects within the array (lets say 4 "friends")
How should I go about implementing a function that searches the existing array (say, if its populated from the API), and inputs the new object with the corresponding ID that is missing (so if the user deletes the object with the id 2, and adds another, it will search said array with objects, find the missing id 2 slot in the array, and input the object in its place)?
Previously I have gone about it via implement array.find() with conditionals to see if the array contains or does not contain the certain id value, however, it searches through each entry and can end up inserting the same object multiple times. Another method I haven't attempted yet would be having a separate map that contains ids, and then when a user removes an object, having it correspond with the map, and vice versa when adding.
Any suggestions? Thanks
Instead of an array, I'd keep an object in data. Have it keyed by id, like this:
let objects = {
0: { id: 0, name: 'name0', relationship: 'relationship0' },
1: { id: 1, name: 'name1', relationship: 'relationship1' },
}
Integer keys in modern JS will preserve insertion order, so you can think of this object as ordered. The API probably returns an array, so do this...
// in the method that fetches from the api
let arrayFromApi = [...];
this.objects = array.reduce((acc, obj) => {
acc[obj.id] = obj; // insertion order will be preserved
return acc;
}, {});
Your UI probably wants an array, so do this (refer to "array" in the markup):
computed: {
array() {
return Object.values(this.objects);
},
To create a new object, insert it in order, minding the available keys. Note this is a linear search, but with small numbers of objects this will be plenty fast
methods: {
// assumes maxId is const like 4 (or 40, but maybe not 400)
createObject(name, relationship) {
let object = { name, relationship };
for (let i=0; i< maxId; i++) {
if (!this.objects[i]) {
object.id = i;
this.objects[i] = object;
break;
}
}
try this,
let array = [
{id: 0, name: "First", relationship: "Friend"},
{id: 4, name: "Second", relationship: "Friend"},
{id: 2, name: "Second", relationship: "Friend"},
]
const addItem = (item) => {
let prevId = -1
// this is unnecessary if your array is already sorted by id.
// in this example array ids are not sorted. e.g. 0, 4, 2
array.sort((a, b) => a.id - b.id)
//
array.forEach(ob => {
if(ob.id === prevId + 1) prevId++
else return;
})
item = {...item, id: prevId + 1 }
array.splice(prevId+1, 0, item)
}
addItem({name: "x", relationship: "y"})
addItem({name: "a", relationship: "b"})
addItem({name: "c", relationship: "d"})
console.log(array)
You can simply achieve this with the help of Array.find() method along with the Array.indexOf() and Array.splice().
Live Demo :
// Input array of objects (coming from API) and suppose user deleted 2nd id object from the array.
const arr = [
{id: 0, name: "First", relationship: "Friend" },
{id: 1, name: "Second", relationship: "Friend" },
{id: 3, name: "Fourth", relationship: "Friend" }
];
// find the objects next to missing object.
const res = arr.find((obj, index) => obj.id !== index);
// find the index where we have to input the new object.
const index = arr.indexOf(res);
// New object user want to insert
const newObj = {
id: index,
name: "Third",
relationship: "Friend"
}
// Insert the new object into an array at the missing position.
arr.splice(index, 0, newObj);
// Output
console.log(arr);

Creating two arr with same intersect

Right now I need to merge the string into one.
This is my try ->
After this merge i got example of array ->
[
[{id: 1, name: "One"}],
[{id: 2, name : "two"}]
]
problem is newData because always print new array.
I need to data be like ->
[
{id: 1, name: "One"},
{id: 2, name : "two"}
]
What i am try, with foreEach ->
newState((oldData) => [...oldData, newData.forEach((new) => new)]);
No work.
Also what I am try
let filteredArray = newData.map(data => data);
Also no work, why?
Every time I get new information inside array newData....
I need solution to get only result inside array and print to
newState((oldData) => [...oldData, newResultWhichIsObject]);
Also some time my newData have few object inside array
The map method isn't the right method to use in your case. Map method will take as an entry an array of n elements and mutate it into an array of n element, on which an operation was applied. See MDN documentation
You should use the reduce method, which provides the ability to construct a brand new array from an empty one, here is the snippet :
const baseArray = [
[{id: 1, name: "One"}],
[{id: 2, name : "two"}]
];
const flattenedArray = baseArray.reduce((acc, curr) => ([...acc, ...curr]), []);
// For demo purpose, console.log
console.log(flattenedArray);
Reduce array method is a bit tricky, that is why I invite you to read the documentation carefully and play with it.
You can use .flat() method. Try this
const newData = [
[{id: 1, name: "One"}],
[{id: 2, name : "two"}]
];
console.log(newData.flat())

Create a subset of data selected on columns in 2d javascript array

Sorry for the basic question and bad lexicon, I am (very) new to javascript. I have an array of data and I would like to create a subset of that data, based on selected columns. The first few rows of my data, for example:
0: {ID: 3607, Name: 'Alamo', Funds: 52933955,
Revenues: 9160109, BAT: 5, …}
1: {ID: 3539, Name: 'Alvin', Funds: 6128147,
Revenues: 964083, BAT: 0, …}
2: {ID: 3540, Name: 'Amarillo', Funds: 12450969,
Revenues: 1716038, BAT: 0, …}
I want to create a new array from columns 0, 1, 2, and 4 (ID, Name, Funds, and BAT). In the code below, toolData is the array created from the original dataset (toolData.json), and tableData is the array I'm trying to create from the selected data. selections contains the column numbers I want to pull into the new array.
var getData = () => axios.get('toolData.json')
.then(res => res.data)
.then(data => {
var toolData = data;
console.log(toolData);
var tableData = [];
var selections = [0,1,2,4];
for (i=0; i < toolData.length; i++)
{
tableData[i] = toolData[i];
for (j=0; selections.length; j++)
{
k = selections[j],
tableData[i][j] = toolData[i][k]
}
}
console.log(tableData);
This particular code snippet doesn't work at all, I'm assuming I've created an infinite loop somehow. If I comment out tableData[i] = toolData[i]; then that problem resolves, but the code still doesn't work. console.log(toolData); gives me what I'm looking for (the full panel of data), but console.log(tableData); gives the error:
javascript.js:42 Uncaught (in promise) TypeError: Cannot set properties of undefined (setting '0')
at javascript.js:42
Ultimately I would like the user to be able to choose the columns they want to include in the new array, but before I can figure that puzzle out I need to solve this one.
Well, it seems from what you're saying is that every index in the array is an object.. arr[0][0]==undefined but arr[0]['ID']==3607
function newSubset(arr,dataToSelect){
//arr is the fetched array, dataToSelect is an array of the keys(like ID,Name...) that you want from the array
return arr.map(obj=>{
var toReturn={} //object that would give each desired key for each part in arr
dataToSelect.forEach(key=>toReturn[key]=obj[key]) //placing wanted keys in toReturn
return toReturn
})
}
//usage
var getData = () => axios.get('toolData.json')
.then(res => res.data)
.then(data => {
var wantedKeys=["ID","Name","Funds","BAT"]
console.log(newSubset(data,wantedKeys))
//rest of your code here
LIVE EXAMPLE
var dataArray=[{ID: 3607, Name: 'Alamo', Funds: 52933955, Revenues: 9160109, BAT: 5}, {ID: 3539, Name: 'Alvin', Funds: 6128147, Revenues: 964083, BAT: 0}, {ID: 3540, Name: 'Amarillo', Funds: 12450969, Revenues: 1716038, BAT: 0}]
function newSubset(arr,dataToSelect){
//arr is the fetched array, dataToSelect is an array of the keys(like ID,Name...) that you want from the array
return arr.map(obj=>{
var toReturn={} //object that would give each desired key for each part in arr
dataToSelect.forEach(key=>toReturn[key]=obj[key]) //placing wanted keys in toReturn
return toReturn
})
}
console.log(newSubset(dataArray,["ID","Name","Funds","BAT"]))
The data is a JSON object. It is not indexed by numbers but rather by names.
It's also recommend to use the built-in map function for this.
const tableData = toolData.map(row => ({
ID: row.ID,
Name: row.Name,
Funds: row.Funds,
BAT: row.BAT
}));
If you want the new toolData array to contain arrays instead of objects, you can instead do:
const tableData = toolData.map(row => [
row.ID,
row.Name,
row.Funds,
row.BAT
]);

Javascript array difference

I have two arrays like so
data = [{id: 1, name: apple},
{id: 2, name: mango},
{id: 3, name: grapes},
{id: 4, name: banana}]
data2 =[{id: 1, name: apple},
{id: 3, name grapes}]
My Expected result would be:
[{ id: 2, name: mango},
{id:4, name: banana}]
My code is
let finalData =[];
data.forEach(result => {
data2.find(datum => {
if(datum['id'] === result['id]{
finalData.push(result);
}
})
})
I am getting wrong result. What is the simplest code or library that I can use?
Your sample data doesn't make sense, but assuming you mean that all data items that have matching IDs also have matching names and also assuming you want a set of all items where the IDs are the same in the two sets of data, you could use a Set to keep track of which IDs are present in one array then filter the second array by those that have their IDs in the set:
const idsInFirst = new Set(data.map(d => d.id));
const intersection = data2.filter(d => idsInFirst.has(d.id));
The reason why an intermediate Set structure is used is because it allows O(1) lookups after a one-time scan, which is more efficient than repeatedly scanning the first array over and over.
If you meant to say you wanted a difference between data sets (items excluded from data that are in data2), you'd want to negate/inverse things a bit:
const idsToExclude = new Set(data2.map(d => d.id));
const difference = data.filter(d => !idsToExclude.has(d.id));
Edit
After your clarifying edit, it's that second block of code that you'll want.
I would say a good way to do that is filtering your longest array using a function that will validate if the object id is present in both arrays. Check this example:
const data = [
{id: 1, name: 'apple'},
{id: 2, name: 'mango'},
{id: 3, name: 'grapes'},
{id: 4, name: 'banana'}
]
const data2 =[
{id: 1, name: 'apple' },
{id: 3, name: 'grapes' }
]
const longest = data.length > data2.length ? data : data2;
const shortest = data.length <= data2.length ? data : data2;
const finalData = longest.filter( obj => !shortest.find( o => o.id === obj.id ) )
console.log(finalData)
Good luck!

Categories