if array contains duplicate, merge both values as one - javascript

I've got an array that looks like:
Is there a way that when another object "AAPL" gets added to the array, the fees and amount gets added and AAPL stays one object in the array?
Thank you in advance!

I wouldn't want to assume that "AAPL" is always within the array.
Check first if the new item is within the array. If not, I will return and end the call (but you may wish to append this to the array instead as it is a new item).
If it is, replace the current object (or parts of the object, in this case I have done just fees & amount)
function addPortfolioItem(item) {
const index = returnPortfolioHoldingIndex(item);
if (index = -1) {
// Returning if not found - You may wish to append to the array as mentioned above
return;
} else {
// Overwrite the object within the array with the new object
portfolioHoldings[index].fees = item.fees;
portfolioHoldings[index].amount = item.amount;
}
}
function returnPortfolioHoldingIndex() {
const tickerSymbolToSearch = "AAPL";
return portfolioHoldings.findIndex(item => item.ticker_symbol === tickerSymbolToSearch);
}

First identify the entry then just add another integer to the value.
It depends on how you are updating that object now - if it's always in 0 position then just portfolioHoldings[0][amount] += number;
if not, then loop through all and check if ticker_symbol == AAPL, then update that array value, by adding needed amount.

Related

React.JS Storing mapped API repsonse into a new array based on matching values

Using React, I have data from an API response. I mapped the data and am storing the visitID, which would be the main identifier, into a variable. What I would like to do is look for any matching visitID values and store them into a new array, the issue I'm having is each instance is being stored in it's own array, for example:
['7065682'] at Index 0
['7065682'] at Index 1
['7065682'] at Index 2
['7047674'] at Index 3
['7047674'] at Index 4
I would like to look through each iteration and check all, put matching values into it's own array so I can write some logic based off each unique value. I just don't understand how to look through the next iteration. Here's my code, and the function 'duplicateVisitID' that I've been trying, but it doesn't give me the results I'm looking for.
{
Object.keys(this.state.EncounterData).length !== 0 ?
Object.values(this.state.EncounterData).map((encounter, i) => {
const visitID = [encounter.resource.identifier[1].value];
console.log(visitID, i);
const duplicateVisitID = function (visitID) {
if (visitID[i] === visitID[i])
return [visitID.concat(visitID[i])]
}
I am not sure what do you want to do, but if I understood right you want new array with only strings that are unique, not repeating. If yes see the code below. This is not the best performing one because of iteration inside iteration, but it will work for you. You can optimize it later by applying some algorithms.
The newArr is equal to ['7065682', '7047674']
const EncounteredData = [['7065682'], ['7065682'], ['7065682'], ['7047674'], ['7047674']];
const newArr = [];
for(let i of EncounteredData) {
for(let j of EncounteredData) {
if((i[0] !== j[0]) && !newArr.includes(i[0])) newArr.push(i[0]);
}
}
console.log(newArr);
If I understand correctly, you want an array of unique values? If so then you can use the map function and add any unique values to an array if the value is not already in it:
const uniqueVals = [];
EncounteredData.map((visitID) => {
if (!uniqueVals.includes(visitID[0])) {
uniqueVals.push(visitID[0]);
}
});

How are the variables populated in this Javacript snippet plus a couple of other questions

I'm a backend developer but would like to figure out this snippet of javacript. I've put some comments on the pieces I get, but have boldfaced questions for the parts I don't.
function transformData (output) {
// QUESTION:
// what the difference between "{}" and "[]" below?
const filteredData = {};
const Statistics = [];
// this is an array of the codes
const NORCA_CODE = [
'QFV1D_START_CHARACTER_CORRECTED',
'QFV1D_STOP_CHARACTER_CORRECTED',
'QFV1D_BUFFER_DECODING_FAILED'
]
// this is to create Series 0, which is the X axis. It just has the systems, e.g, 01, 02,
// etc.
/* Series 0 */
// Here it's creating data0.
// It's going to use an array function to create a set
// Any system name it finds, it's going to put it in data0, then it will sort it
const data0 = Array.from(new Set(output.map(({ systemName }) => systemName))).sort();
// It's going to create a series0 json object which will probably
// look like "["systemName": "01","systemName": "02", ...]
var series0 = {
name: 'systemName',
data: data0.map(d => `System ${d}`)
}
// The system / name series will be pushed to a Statics object as series 0 for the graph
Statistics.push(series0);
// This looks like it's going to iterate over data0, which contains systems,
// and for each system, iterate over the output
// (which is actually input from an API)
// And if the system name matches is going to add to "acc" (accumulated total
// for the system if the input (cur.system name) matches the system name
// from from data0 (systems)
// QUESTIONS:
// question 1 - where is acc coming from? Is it a dynamic variable?
// question 2 - why does it return acc if there's no match? To give the current system
// the same total it had previously?
// question 3 - why does it return a zero at the end? How does it fit into the picture?
// question 4 - Is this getting total objects for the system?
const norcaBase = data0.map(systemName => output.reduce((acc, cur) => {
if (cur.systemName === systemName) {
return acc + cur.sum
}
return acc
}, 0))
// Create an array of norca data
const norcaData = {}
// iterate through the NORCA codes
NORCA_CODE.forEach((code) => {
// for the current code iterate through the system names
norcaData[code] = data0.map(systemName => output.reduce((acc, cur) => {
// if the system name and code match, accumulate
if (cur.systemName === systemName && cur.norcaCode === code) {
return acc + cur.sum
}
return acc
}, 0))
})
// iterate through the NORCA Codes
// question: is "i" an increment?
NORCA_CODE.forEach((code, i) => {
// Push the code and percentage of total into Statistics
// QUESTION
// question: where does "d" from? looks the the total for that Norca Code
Statistics.push({
name: code,
data: norcaData[code].map((d, i) => norcaBase[i] ? d / norcaBase[i] : 0)
})
})
// Put the chart-data entry in filteredData
filteredData['chartData'] = {};
// Put the Statistics into chart data
filteredData['chartData']['Statistics'] = Statistics;
// return filtered daa
return filteredData;
}
// what the difference between "{}" and "[]" below?
{} creates an object. Javascript objects are similar to maps or dictionaries in other languages and store unordered key/value pairs. [] creates an array for storing ordered data.
Taking your questions out of order:
// question 4 - Is this getting total objects for the system?
Generally speaking, the purpose of reduce is to step through an array, and "combine" elements of the array. You provide a function which describes how you want to combine them. Reduce will then step through the array, calling your function for every element of the array. When it calls your function it passes in the value so far (often called the "accumulator"), and the element of the array currently being looked at, and then your function is responsible for returning the new value of the accumulator.
In your specific case, this code is adding up the .sum properties of every element in the array who's systemName matches.
// question 3 - why does it return a zero at the end?
That 0 is the initial value of the accumulator. It's being passed into reduce, not returned.
// question 1 - where is acc coming from?
It's passed in to you by the code for reduce. acc will be 0 the first time your function is called (see question 3), and on subsequent calls it will be whatever value you returned the last time.
// question 2 - why does it return acc if there's no match?
Because this code wants the accumulator to not change for that case. Ie, it's not adding anything to it.
// question: is code an increment?
Not sure what you mean by an increment. .forEach will loop over each element of the array and call the function you provided for each of them. The first argument that will be passed in (here named code) is the element of the array.
// question: where does "d" from?
.map will call the function you provide once for each element of the array. The first argument is the element of the array. The difference between .map and .forEach is that with .map you are creating a new array, the values of which are whatever you return via your function (.forEach pays no attention to what you return).

Loop through multiple values and remove from array

I have an event that attempts to remove items from a list. Currently trying to use splice to remove them from the array of objects. I need to use a function that acutally uses the original array. As I want so see the change happen live in the frontend. The code below works to a certain extent, but only seems to remove some items per click.
Controller
$scope.clearAlerts = function(type) {
var array = [];
for (let item of $scope.notifications) {
if (item.read && type == 'seen') {
notifications.clearAlerts(item.watching_id);
//console.log(item.watching_id)
}
if (!item.read && type == 'notseen') {
notifications.clearAlerts(item.watching_id);
//console.log(item.watching_id) - This returns 8 items
}
}
}
Service
this.clearAlerts = function(watchingId = null) {
// Remove notifications
this.notifications.forEach((item, index, object) => {
if (item.watching_id === watchingId) {
//remove alerts from dom
object.splice(index, 1); - This only removes 2 or 3 per click
index--;
// update database
//return api.request('GET', 'notification/' + watchingId + '/clear', {watching_id: watchingId});
}
});
}
Any help on this would be much appreciated. Thanks
So if you were to use an object instead of an array where the keys of the object were say the ID you are watching then your service function should look something like this...
this.clearAlerts = function(watchingId = null) {
delete this.notifications[watchingId];
}
Much simpler, so the idea is that instead of using an array as in [object, object], us an object that is mapped out something like so
{
id1: object,
id2: object,
...
}
where id1, and id2 are actually taken from watching_id which you defined
As for the reason why your alerts aren't removed accurately is because you are mutating the array you are looping through.
Here is an example
const notifications = [
{
watching_id: 1
},
{
watching_id: 2
},
{
watching_id: 3
},
{
watching_id: 4
}
];
notifications.forEach((item,index, arr) => {
if (item.watching_id > 0) {
arr.splice(index, 1);
}
})
In this example at first sight it can seem that all items are going to be deleted, but that is not the case.
When the index is 0, you delete the first item, and after deletion you have an array with 3 items, so on the second iteration when the index is 1 you are deleting the item from 3 items array which index is 1 and that is the second item out of 3, the first item is intact.
As a solution you can add the third argument to the splice, in order to have the same length array, which will solve the problem. Decide yourself what is best for your specific case, 3rd argument can be anything null,'undefined' or an object object.splice(index, 1, {}).
By the way, index-- doesn't do anything, index is set on every iteration.

Looping through an array with conditions

I'm having a tough time figuring out how to loop through an array and if certain items do exist within the array, i'd like to perform a .slice(0, 16) to kind of filter an already existing array (lets call that existing array "routes").
For example, a previous process will yield the following array:
points = ['=00ECY20WA200_RECV_P1SEL',
'=00ECY20WA200_RECV_P2SEL',
'=00RECV_C1A_EINCSCMPP1',
'=00RECV_C1A_EINCSCMPP2',
'=00BYPS_C1A_EINCSCMP',
'=00ECY20WA200_BYPS_SPSL1',
'=00ECC92AG184YB01',
'=00ECC92AG185YB01',
'=00ECC92AG186YB01',
'=00ECC92AG187YB01',
]
So if any of the above items exist in the "points" Array, which in this case they all do (but in some cases it could just be 1 of the 10 items existing there), I'm trying to perform routes.slice(0, 16) to the other already existing array.
I've tried lots of different ways (for loops with if statements) and at this point I'm not sure if its my syntax or what, but I'm back at square 0 and I don't even have a competent piece of code to show for. Any direction would be greatly appreciated.
You could use a hash table for checking and filtering.
var points = ['=00ECY20WA200_RECV_P1SEL', '=00ECY20WA200_RECV_P2SEL', '=00RECV_C1A_EINCSCMPP1', '=00RECV_C1A_EINCSCMPP2', '=00BYPS_C1A_EINCSCMP', '=00ECY20WA200_BYPS_SPSL1', '=00ECC92AG184YB01', '=00ECC92AG185YB01', '=00ECC92AG186YB01', '=00ECC92AG187YB01'],
hash = Object.create(null),
filtered = points.filter(function (a) {
if (!hash[a.slice(0, 16)]) {
hash[a.slice(0, 16)] = true;
return true;
}
});
console.log(filtered);
ES6 with Set
var points = ['=00ECY20WA200_RECV_P1SEL', '=00ECY20WA200_RECV_P2SEL', '=00RECV_C1A_EINCSCMPP1', '=00RECV_C1A_EINCSCMPP2', '=00BYPS_C1A_EINCSCMP', '=00ECY20WA200_BYPS_SPSL1', '=00ECC92AG184YB01', '=00ECC92AG185YB01', '=00ECC92AG186YB01', '=00ECC92AG187YB01'],
pSet = new Set,
filtered = points.filter(a => !pSet.has(a.slice(0, 16)) && pSet.add(a.slice(0, 16)));
console.log(filtered);
EDIT: So it seems like you want to remove an element from an array called routes for each element in the points array. This is how you could do this:
function removeBrokenRoutes(brokenPoints, routes){
for(let pt of brokenPoints){
let index = routes.indexOf(pt);
if(index !== -1) routes.splice(index,1);
}
return routes;
}
Keep in mind that the larger the arrays, the more time this is going to take to complete.
You could use the filter and indexOf methods in combination:
var arr = [/* all the data you're checking against */];
var points = [/* the data you're checking for */];
var filteredArr = arr.filter(function(x) {
// will return -1 if the point is not found
return points.indexOf(x) !== -1;
});
filteredArr will contain all the points that appear in both arrays. The filter function works by taking a function with one argument x, which represents each item in the array. if the function returns true, the item will be added to the new array (filteredArr), and if false the function will move on to the next item. indexOf will check if the item is found in the other array. Also it is important to note that you will need a more complex solution (such as a hashtable) if the data set is very, very large as this is not necessarily the most performant method. But it's a good place to start as it is easy to understand.

Keeping the last element in an array with the same property

Let's imagine I have this array:
bucket.bucketList =[];
bucket.addItem = function(item) {
bucket.bucketList.push(item);
}
The function pushes an object called foo this into the array on every mouse-scroll:
Some foo's also have a property , foo.name = "something";
The question is, what is the best way to delete All duplicates based on their name property names whilst keeping the most recents one pushed in?
I am using jQuery already in my project, so if jQuery has a more elegant way of doing this than vanilla JS i'd be more than happy to use it.
This code removes all duplicate names, keeping the last one in the array.
You can traverse backwards through the array and remove any items with a name that you've already seen, using an object to keep track of the names you've already seen. By traversing backwards, you keep the last one and you don't have to do any array index corrections when you remove the current entry from the array:
var dict = {}, item;
for (var i = bucket.bucketList.length - 1; i >= 0 ; i--) {
item = bucket.bucketList[i];
if (item.name) {
// if already in the dict, remove this array entry
if (dict[item.name] === true) {
bucket.bucketList.splice(i, 1);
} else {
// add it to the dict
dict[item.name] = true;
}
}
}

Categories

Resources