Count duplicate property values of a nested Javascript object - javascript

I'm feeding in information in from an API with the format -
Records = { 0: {fields: {name: "nameExample" place: "placeExample"} }
{1: {fields: {name: "nameExample" place: "placeExample"} }
etc etc
I'm looking for a way to count duplicates of the 'place' field in the format: Scotland(4), London(6) etc. where the number is the amount of times it repeats.
The closest I've got as of yet is counting the letters in each place name, but I'm not sure what I'm doing wrong. I think if I can get them in the same array then it would be simple, but when I tried to do that it put each place in a different array.
Also must be vanilla javaScript, no jQuery. Many thanks!
var URL = new Array();
URL[0] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45";
URL[1] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45&offset=45";
URL[2] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45&offset=90";
var nRequest = new Array();
for (var i=0; i<3; i++){
(function(i) {
nRequest[i] = new XMLHttpRequest();
nRequest[i].open("GET", URL[i], true);
nRequest[i].onreadystatechange = function (oEvent) {
if (nRequest[i].readyState === 4) {
if (nRequest[i].status === 200) {
var data = JSON.parse(nRequest[i].responseText);
var url = 'http://media.vam.ac.uk/media/thira/collection_images/';
for (let key in data.records) {
let value = data.records[key];
let image = value.fields.primary_image_id;
let res = image.substr(0, 6);
document.querySelector(".map").innerHTML += '<div class="' + value.fields.place + ' map"> ' + value.fields.place + ' <br> </div>';
}
} else {
console.log("Error", nRequest[i].statusText);
}
}
//
};
nRequest[i].send(null);
})(i);
};

If thats the data structure you can solve it like so:
const Records = [
{fields: {name: "nameExample", place: "placeExample"}},
{fields: {name: "nameExample", place: "placeExample"}}
];
const result = Records.reduce((acc, {fields}) => {
if(acc[fields.place]) acc[fields.place]++;
else acc[fields.place] = 1;
return acc;
}, {})
console.log(result);

You can use the reduce function to convert the array data.records to an object with the place as key and number of occurrences as value.
data.records.reduce((accum, currVal) => {
if (!(currVal.fields.place in accum)){
accum[currVal.fields.place] = 0;
}
accum[currVal.fields.place] += 1;
return accum;
}, {});

Related

Unable to bind data to dropdown-multiselect in angularjs

Please check the plunker. I'm not able to bind the data which come from server like this(["Monday","Tuesday"]).
I know data binds when it is like
$scope.selectedUser = [{ id: 2, name: 'Monday' },
{id: 3,name:'Tuesday'}];.
I want to make ["Monday","Tuesday"] to [{ id: 2, name: 'Monday' },{id: 3,name:'Tuesday'}] in javascript so that it would bind in dropdown.
Please help me solve this issue.
demo plunker
//This is the ng filter to create id as you get the data from server
app.filter('createId',function(){
return function(arr){
var result = [];
for(var i = 0;i < arr.length;i++){
var id = arr[i].substring(0,3);
var obj = {'id':id,'name':arr[i]};
result.push(obj);
}
return result;
}
});
//In js controller you can costomize your array of user by using ng-filter like this
$scope.users = $filter('createId')($scope.users);
//This is because index will be changed every time so this can't be used as ID
$scope.selectedUser = $filter('createId')($scope.selectedUser);
Achieve your json using below code
var temp = ["Monday", "Tuesday"]
var result = "[";
for (var i = 0; i < temp.length; i++) {
if(i!=temp.length-1)
{
result += "{id:'" + i + "',name:'" + temp[i] + "'},";
}
else
{
result += "{id:'" + i + "',name:'" + temp[i] + "'}";
}
alert(result);
}
console.log(result+"]")
You can do this
$scope.selectedUsers=[];
//serverData is data from server
for(var i =0 ; i < serverData.length ; i++){
$scope.selectedUsers.push({id:i , name: serverData[i]})
}
And in your angular
$scope.doSelectedUser = function () {
$scope.selectedUser = $scope.selectedUsers;
}
$scope.selectedUser should have a reference to the actual objects in $scope.users. for example, this is what i had to change in your plunker to bind it with the users match the user names list:
var defaultSelectedUsers = ["Sunday","Tuesday"];
$scope.users = [
{ id: 1, name: 'Sunday' },
{ id: 2, name: 'Monday' },
{ id: 3, name: 'Tuesday' } ];
$scope.selectedUser = $scope.users.filter(function(user){
return defaultSelectedUsers.indexOf(user.name) != -1;
});
Online Demo - http://plnkr.co/edit/3TOkZEaZVSxtpNbFaNkg?p=preview
You mentioned you want to do it from your server's response. it's unclear how you want to decide which one to select, assuming you rely on a default selected users by name according your example.
This is how you handle a server's response and modify the new selected users:
var defaultSelectedUsers = ["Sunday","Tuesday"];
$http.get('/api/v1/users')
.success(function(users)){
$scope.users = users;
$scope.selectedUser = users.filter(function(user){
return defaultSelectedUsers.indexOf(user.name) != -1;
});
});
You may change the filter condition to what makes sense for you

How to find duplicated title values in a map

I'm new to Javascript, come from Java, this is less intuitive for me.
I would like to check for duplication of the title value and concatenate to the duplicated title the producer name
My idea is to sort the values and then check each one with is next for duplication
Can you suggest me how to implement this kind of solution?
function getItems(itemKeys, itemSortOrders, itemsMap)
{
var items = _.map(itemKeys, function(itemKey, index) {
var item = itemsMap[itemKey];
return _.extend({
key: itemKey,
title: item.title,
imageURL: item.imageURL,
formattedPrice: utils.formatMoney(item.price),
producerKey: item.producerKey,
producerTitle: item.producerTitle,
allowOrder: true,
sortOrder: itemSortOrders[index]
}, calculateItemDetails(item.deliveryDayAvailable, item.deliveryDayStatus, item.deliveryDayUsageCount));
});
items = _.compact(items);
return items;
}
Thanks
You can test if item have duplicates with this function, it use filter to find the same items and check if the length is larger then 1.
function haveDuplicates(itemKeys, itemsMap, itemKey) {
var item = itemsMap[itemKey];
var dups = itemKeys.filter(function(key) {
return itemsMap[key] == item;
});
return dups.length > 1;
}
var itemsMap = {
'foo': 'Lorem',
'bar': 'Lorem',
'baz': 'Ipsum',
'quux': 'Dolor'
};
var output = document.getElementById('output');
var itemKeys = Object.keys(itemsMap);
itemKeys.map(function(key) {
output.innerHTML += itemsMap[key] + ' ' +
(haveDuplicates(itemKeys, itemsMap, key) ? 'have' : 'don\'t have') + '\n';
});
<pre id="output"></pre>
SO this is what i did eventually and this worked
var duplicateMap = {};
_.each(itemsMap, function(item) {
var title = item.title.trim();
if (duplicateMap[title]) {
duplicateMap[title] = 2;
}
else {
duplicateMap[title] = 1;
}
});

Removing an item from a two dimensional Javascript Array

I have a simple array like this:
var CutRoadArray = [
['Location', '_Location'],
['Applicant Info', '_ApplicantInfo'],
['Details', '_ApplicationDetails'],
['Bond Info', '_BondInfo'],
['Attachments', '_Attachments'],
['Review', '_ReviewA']
];
I would like to check if this array contains the entry
['Bond Info', '_BondInfo'],
And if it does, remove it. In a separate scenario, I would like to search for the same, and if it doesnt exist, add it at a certain index.
I have tried various ways, none worked. Any help will be much appreciated.
One of the ways I have tried to accomplish this is:
Array.prototype.remove = function () {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
};
function indexOfRowContainingId(id, matrix) {
var arr = matrix.filter(function (el) {
return !!~el.indexOf(id);
});
return arr;
}
Then calling something like:
var bond = indexOfRowContainingId('_BondInfo', CutRoadArray);
if (bond.length > 0) {
var ar = CutRoadArray.remove("['Bond Info', '_BondInfo']");
console.log(ar);
}
Try this:
var CutRoadArray = [
['Location', '_Location'],
['Applicant Info', '_ApplicantInfo'],
['Details', '_ApplicationDetails'],
['Bond Info', '_BondInfo'],
['Attachments', '_Attachments'],
['Review', '_ReviewA']
];
var testElem = ['Bond Info', '_BondInfo'];
for(var i=0; i<CutRoadArray.length; i++){
var temp = CutRoadArray[i].toString();
if(temp === testElem.toString()){
//remove element from array
CutRoadArray.splice(i, 1);
break;
}
}
console.log(CutRoadArray);
This function has your desired functionality:
function testArray(test, array){
return array.filter(function(x){
return x.toString() != test;
})
}
testArray(['Bond Info', '_BondInfo'], CutRoadArray)

Count times a value is repeated in data fetched using REST call

I'm fetching data from SharePoint using REST, and everything works just fine, except that I would like to count the times the same item appears.
This is the jQuery:
var url = "https:xxxxxxxx/_vti_bin/ListData.svc/RMSD_Tasks?$orderby=TypeOfIssueValue asc,StatusValue desc&$filter=StatusValue ne 'Completed'&groupby=TypeOfIssueValue/StatusValue";
var lastIssue = '';
$.getJSON(url, function (data) {
$('#totalCounter').text(data.d.results.length);
for (var i = 0; i < data.d.results.length; i++) {
var dateReceived = data.d.results[i].DateReceived;
dateReceived = new Date(parseInt(dateReceived.replace("/Date(", "").replace(")/", ""), 10)).toLocaleString('en-US', {
year: 'numeric',
month: 'numeric',
day: '2-digit'
});
var issue = data.d.results[i].TypeOfIssueValue;
console.log(data.d.results[i].TypeOfIssueValue);
if (issue != lastIssue) {
lastIssue = issue;
$('#myDataList').append('' + issue + '<span class="badge">' + issue.length + '</span>');
}
}
});
I need to count how many time a specific TypeOfIssueValue appears. When I see the console it shows exactly what I would like to add to me info:
I just added a issue.length in the badge were I want to insert the number for the sake of just having something there, but I know it won't show what I want. Thanks!
var data = {
d: {
results: [
{ TypeOfIssueValue: '456' },
{ TypeOfIssueValue: '123' },
{ TypeOfIssueValue: '789' },
{ TypeOfIssueValue: '123' }
]
}
};
var filteredItems = data.d.results.filter(function(item){
return item.TypeOfIssueValue == '123';
});
var count = filteredItems.length;
document.getElementById("output").innerHTML = "Number of items with value '123': " + count;
<div id="output"/>
You could first map the TypeOfIssueValue values to a new array and then count each occurence based on this answer.
The code would be :
var a = data.d.results.map(function(issue) {
return issue.TypeOfIssueValue
});
result = {};
for (i = 0; i < a.length; ++i) {
if (!result[a[i]])
result[a[i]] = 0;
++result[a[i]];
}
The result will be an object with property being type of issue and value being the count of each.
Let me know if this makes sense.
Thanks #srinivas. I accepted your response, although I made some modifications, just in case they are useful to someone else.
I added a class to the span badge and added a new array to push the issues:
issuesArray.push(data.d.results[i].TypeOfIssueValue);
$('#myDataList').append('' + issue + '<span class="badge badgeSpan"></span>');
Then I addded a done() to run after the getJSON:
.done(
function(){ var resultado = foo(issuesArray)[1];
console.log(resultado);
var badges = $('.badgeSpan');
for (var j = 0; j < resultado.length; j++){
badges[j].innerHTML = resultado[j];
}
});
Last I made a small modificfation to the function foo() that you provided:
testArray = [];
function foo(arr) {
var a = [], b = [], prev;
for ( var i = 0; i < arr.length; i++ ) {
if ( arr[i] !== prev ) {
a.push(arr[i]);
b.push(1);
} else {
b[b.length-1]++;
}
prev = arr[i];
}
testArray.push(a,b)
return testArray;
}
This maybe a very unorthodox solution, but it worked for me. Thanks again.

javascript array - accessing json type of objects

The code:
function getDummyDetails(){
var userDetailsMap = [];
userDetailsMap.push({key:'APPCODE', value:'41'});
userDetailsMap.push({key:'WORKERNUMBER', value:'1234567'});
userDetailsMap.push({key:'ACCOUNTID', value:'DEVELOP'});
userDetailsMap.push({key:'NAMEFIRST', value:'John'});
userDetailsMap.push({key:'NAMELAST', value:'Developer'});
return userDetailsMap;
}
function someOtherFunction () {
var userDetails = getDummyDetails();
document.getElementById("userName").innerHTML = "User Name: " + userDetails[3].value + ", " + userDetails[4].value;
}
Here, it works fine but I can not use the array index here like userDetails[3].value. I was trying to do something like this
userDetails["APPCODE"].value; // just a pseudo code
How can I index this array with that string values but not an integer?
You should create an object instead of an array. That way you'll be able to access it via its key:
function getDummyDetails() {
return {
'APPCODE':'41',
'WORKERNUMBER':'1234567',
'ACCOUNTID':'DEVELOP',
'NAMEFIRST':'John',
'NAMELAST':'Developer'
};
}
function someOtherFunction () {
var userDetails = getDummyDetails();
userDetails["APPCODE"] // 41 - use it however you want...
}
You need to create an object, not an array:
var userDetailsMap = {
APPCODE:41
}
var value = userDetailsMap["APPCODE"];//value now = 41
If you don't want to change your structure, you can iterate over your array:
for (var i = 0, len = userDetailsMap.length; i < len; i++) {
if (userDetailsMap[i].key == 'APPCODE') {
var val = userDetailsMap[i].value;
// do something with the value here
}
}

Categories

Resources