Javascript - count and remove from an object - javascript

I have an object with duplicate values and I want to count all those which have the same value and remove them.
var myArray = [{nr: 'bbc',}, {nr: 'bbc'}, {nr: 'bbc'}, {nr: ccc}];
from this array I want to create another array but remove the duplicated values and count them to be like this.
var myArray = [{nr: 'bbc',amount: 3}}, {nr: ccc,amount: 1}];

You could probably use a better format
var count = {};
for(var i = 0; i < myArray.length; ++i) {
if(typeof count[myArray[i].nr] == 'undefined') {
count[myArray[i].nr] = 0;
}
++count[myArray[i].nr];
}
and this wound yield somehing like:
count = {
bcc: 3,
ccc: 1
};
if you still need it with the structure you specified, then:
var newArray = [];
for(var k in count) {
newArray.push({
nr: k,
amount: count[k]
});
}

If you want the same structure, this will work for you
var newArray = [];
for (var i = 0; i < myArray.length; i++) {
var matched = false;
for (var j = 0; j < newArray.length; j++) {
if(myArray[i].nr === newArray[j].nr){
matched = true;
newArray[j].amount++;
break;
}
};
if(!matched)
newArray.push({nr:myArray[i].nr,amount:1});
};
console.log(newArray);

Related

I am stuck at a JavaScript function that should count all unique items in an array

I wanted to create a function, that counts all unique Items in an array, but somehow I do not get any output.
This is my array!
let arr = ["hi", "hello", "hi"];
And this is the code I wrote so far:
function countUnique(arr) {
var counts = {};
for (var i = 0; i < arr.length; i++) {
counts[arr[i]] = 1 + (counts[arr[i]] || 0);
}
countUnique(arr);
}
console.log(countUnique(arr));
Your are counting values correctly, however then you are calling this method recursively countUnique(arr); and it results an error of call stack exceeded.
So just remove recursive call of method countUnique(arr); and return counted value counts:
function countUnique(arr) {
var counts = {};
for (var i = 0; i < arr.length; i++) {
counts[arr[i]] = 1 + (counts[arr[i]] || 0);
}
return counts;
}
let arr = ["hi", "hello", "hi"];
console.log(countUnique(arr));
JavaScript engine limits the maximal recursion depth. We can rely on it being 10000, some engines allow more.
You could take a Set and return the size.
const countUnique = array => new Set(array).size;
console.log(countUnique(["hi", "hello", "hi"]));
let arr = ["hi", "hello", "hi"];
function countUnique(arr) {
var counts = {};
for (var i = 0; i < arr.length; i++) {
if(arr[i] in counts) {
counts[arr[i]]++;
} else {
counts[arr[i]] = 1;
}
}
return Object.keys(counts).length;
}
console.log(countUnique(arr));

JS delete duplicated items from array without higher order functions

I know it's a stupid question, but I only learning programming 3 months now.
How would you solve this problem, if you can't use higher order functions and built-in methods, like filter or indexOf?
Create a function that takes a list of numbers and returns a new list where all the duplicate values are removed
I got this so far, but I think It's a dead end...
const array = [1, 2, 3, 3, 1];
const removeDuplicate = () => {
let shortArray = [];
let index = 0;
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array.length; j++) {
if (i != j) {
if (array[i] == array[j]) {
shortArray[index] += array[i]
console.log(array[i]);
}
}
}
}
return shortArray;
}
console.log(removeDuplicate());
return this:
1
3
3
1
[ NaN ]
thanks!
Use an object as a helper. If a value appears in the helper, it's not unique and can be ignored. If it's not in the helper it's unique, push it into the result array, and add it to the helper object.
const array = [1, 2, 3, 3, 1];
const removeDuplicate = (arr) => {
const helperMap = {};
const result = [];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (!helperMap[item]) {
result[result.length] = item;
helperMap[item] = true;
}
}
return result;
};
console.log(removeDuplicate(array));
function unique(arr) {
var obj = {};
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
obj[value] = true; // set as key
}
return Object.keys(obj); //return all keys
}
Use below function:
function RemoveDuplicate(array){
let shortArray = [];
let index = 0;
for (let i = 0; i < array.length; i++) {
let exist=false;
for(let j=0;j<shortArray.length;j++){
if(array[i]==shortArray[j]){
exist=true;
break;
}
}
if(!exist){
shortArray[shortArray.length]=array[i];
}
}
return shortArray;
}

Push elements of an array to different keys using Javascript & Angular JS

I'm having an array [0,1,2]. I'm trying to assign the array values to an JSON Object as image1:0, image2:1, image3:2, using Javascript but I'm getting confused. Please find my code here
var app = angular.module('app',[]);
app.controller('EventController',function EventController($scope) {
$scope.count = 0;
$scope.next = function() {
var arr = [0,1,2];
var result = {};
for(var i = 0; i < arr.length; i++) {
result.image1 = arr[i];
result.image2 = arr[i];
result.image3 = arr[i];
}
console.log(result)
}
});
My expected result is Object {image1: 0, image2: 1, image3: 2}
But actual result coming is Object {image1: 2, image2: 2, image3: 2}
My fiddle http://jsfiddle.net/Zvy2c/67/
You may use the bracket operator for accessing the property
for (var i = 0; i < arr.length; i++) {
result['image' + (i + 1)] = arr[i];
}
You are looping through arr and assigning the same value to all your properties. You set everything to 0, then 1, then 2.
Forget about the for loop and just set the properties to whichever entry in the array you want:
var arr = [0,1,2];
var result = {
image1: arr[0],
image2: arr[1],
image3: arr[2]
};
var app = angular.module('app',[]);
app.controller('EventController',function EventController($scope) {
$scope.count = 0;
$scope.next = function() {
var arr = [0,1,2];
var result = {};
for(var i = 0; i < arr.length; i++) {
result['image' + (i+1)] = arr[i];
}
console.log(result)
}
});
You need to change your for loop as
for(var i = 0; i < arr.length; i++) {
result['image'+i] = arr[i];
}

rearrange Array according to values order of another Array

I have two arrays like below
var arr = ["x", "y", "z", "a", "b", "c"];
var tgtArr = [{val:"a"}, {val:"b"}]; It does not need to be as lengthy as Array `arr`
This is what I have tried
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
for(var k = 0; k < tgtArr.length; k++){
dest[i] = dest[i] || [];
if(tgtArr[k].val == arr[i]){
dest[i] = arr[i];
}
}
}
console.log(dest);
My Expected output is (for above tgtArr value)
[{}, {}, {}, {val:"a"}, {val:"b"}, {}];
if tgtArr is empty Array
[{},{},{},{},{},{}]
Here is the fiddle. Any alternative for this, it seems not a good way to me as I am iterating through the entire array everytime.
Short:
var result = arr.map(function(x) {
return tgtArr.some(function(o) { return o.val == x; }) ? {val:x} : {};
});
This is more efficient:
var set = {};
tgtArr.forEach(function(obj, i) {
set[obj.val] = true;
});
var result = arr.map(function(x) {
return x in set ? {val:x} : {};
});
This is the same as Paul's answer, but with a loop instead of map. It collects the keys first based on the val property, then creates a new array either with empty objects if the key isn't in tgtArr, or copies a reference to the object from tgtArr if it is:
function newArray(arr, tgtArr) {
var keys = {},
i = tgtArr.length,
j = arr.length,
newArr = [];
// Get keys
while (i--) keys[tgtArr[i].val] = tgtArr[i];
// Make new array
while (j--) newArr[j] = arr[j] in keys? keys[arr[j]] : {};
return newArr;
}
It should be efficient as it only traverses each array once.
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
dest[i] = {}
for(var k = 0; k < tgtArr.length; k++){
if(tgtArr[k].val == arr[i]){
dest[i] = tgtArr[k];
}
}
}
console.log(dest);
I like using map rather than loops for this kind of thing (Fiddle):
var result = arr.map(function(x) {
var match = tgtArr.filter(function(y) {
return y.val == x;
});
if (match.length == 1) return match[0];
else return {};
});
This is a possibly inefficient, in that it traverses tgtArr for every item in arr, so O(n*m). If needed, you could fix that by pre-processing tgtArr and converting it to a hash map (Fiddle). This way you've got an O(n+m) algorithm (traverse each array once):
var tgtMap = {};
tgtArr.forEach(function(x) { tgtMap[x.val] = x; })
var result = arr.map(function(x) {
var match = tgtMap[x];
return match || {};
});
var tmp = {};
for (var i = 0; i < tgtArr.length; i++) {
tmp[tgtArr[i].val] = i;
}
var dest = [];
for (var i = 0; i < arr.length; i++) {
var obj= tmp[arr[i]] === undefined ? {} : tgtArr[tmp[arr[i]]];
dest.push(obj);
}
DEMO

How to merging javascript arrays and order by position?

Is there anyway to merge arrays in javascript by ordering by index/position. I'm try to accomplish this and haven't been able to find any examples of this.
var array1 = [1,2,3,4]
var array2 = [a,b,c,d]
var array3 = [!,#,#,$]
var merged array = [1,a,!,2,b,#,3,c,#,4,d,$]
I know you can use concat() to put one after the other.
As long as the arrays are all the same length you could just do:
var mergedArray = [];
for (var i = 0, il = array1.length; i < il; i++) {
mergedArray.push(array1[i]);
mergedArray.push(array2[i]);
mergedArray.push(array3[i]);
}
EDIT:
For arrays of varying lengths you could do:
var mergedArray = [];
for (var i = 0, il = Math.max(array1.length, array2.length, array3.length);
i < il; i++) {
if (array1[i]) { mergedArray.push(array1[i]); }
if (array2[i]) { mergedArray.push(array2[i]); }
if (array3[i]) { mergedArray.push(array3[i]); }
}
This should work for arrays of ANY length:
var mergeArrays = function () {
var arr = [],
args = arr.slice.call(arguments),
length = 0;
for (var i = 0, len = args.length; i < len; i++) {
length = args[i].length > length ? args[i].length : length;
}
for (i = 0; i < length; i++) {
for (var j = 0; j < len; j++) {
var value = args[j][i];
if (value) {
arr.push(value);
}
}
}
return arr;
};
Example:
var array1 = [1,2,3,4];
var array2 = ['a','b','c','d','e','f','g','h','i','j','k','l'];
var array3 = ['!','#','#','$','%','^','&','*','('];
mergeArrays(array1, array2, array3);
// outputs: [1, "a", "!", 2, "b", "#", 3, "c", "#", 4, "d", "$", "e", "%", "f", "^", "g", "&", "h", "*", "i", "(", "j", "k", "l"]
This would work also (a little more terse syntax):
var mergeArrays = function () {
var arr = [],
args = arr.slice.call(arguments),
length = Math.max.apply(null, args.map(function (a) { return a.length; }));
for (i = 0; i < length; i++) {
for (var j = 0, len = args.length; j < len; j++) {
var value = args[j][i];
if (value) {
arr.push(value);
}
}
}
return arr;
};
For arrays that are all the same size, where you pass one or more arrays as parameters to merge:
function merge()
{
var result = [];
for (var i=0; i<arguments[0].length; i++)
{
for (var j=0; j<arguments.length; j++)
{
result.push(arguments[j][i]);
}
}
return result;
}
var array1 = ['1','2','3','4'];
var array2 = ['a','b','c','d'];
var array3 = ['!','#','#','$'];
var merged = merge(array1, array2, array3);
Nothing built in, but it wouldn't be hard to manage:
var maxLength = Math.max(array1.length, array2.length, array3.length),
output = [];
for (var i = 0; i < maxLength; i++) {
if (array1[i] != undefined) output.push(array1[i]);
if (array2[i] != undefined) output.push(array2[i]);
if (array3[i] != undefined) output.push(array3[i]);
}
try this...
var masterList = new Array();
var array1 = [1,2,3,4];
var array2 = [a,b,c,d];
var array3 = [!,#,#,$];
for(i = 0; i < array1.length; i++) {
masterList.push(array1[i]);
masterList.push(array2[i]);
masterList.push(array3[i]);
}
It looks like you want to "zip" some number of same-length arrays into a single array:
var zip = function() {
var numArrays=arguments.length
, len=arguments[0].length
, arr=[], i, j;
for (i=0; i<len; i++) {
for (j=0; j<numArrays; j++) {
arr.push(arguments[j][i]);
}
}
return arr;
};
zip([1,2], ['a', 'b']); // => [1, 'a', 2, 'b']
zip([1,2,3], ['a','b','c'], ['!','#','#']); // => [1,'a','#',...,3,'c','#']
If the input arrays could be of different length then you've got to figure out how to deal with that case...
Yes, there is some way to do that. Just:
loop through the larger array,
until at the currently processed position both arrays have elements, assign them one-by-one to the new array,
after the shorter array ends, assign only elements from the longer array,
The resulting array will have the elements ordered by the index from the original arrays. From your decision depends, position in which one of these arrays will have higher priority.
This works for any number of array and with arrays of any length.
function myMerge() {
var result = [],
maxLength = 0;
for (var i = 0; i < arguments.length; i++) {
if (arguments[i].length > maxLength) { maxLength = arguments[i].length; }
}
for (var i = 0; i < maxLength; i++) {
for (var j = 0; j < arguments.length; j++) {
if (arguments[j].length > i) {
result.push(arguments[j][i]);
}
}
}
return result;
}
Eli beat me to the punch up there.
var posConcat = function() {
var arrays = Array.prototype.slice.call(arguments, 0),
newArray = [];
while(arrays.some(notEmpty)) {
for(var i = 0; i < arrays.length; i++) {
if(arguments[i].length > 0)
newArray.push(arguments[i].shift());
}
}
return newArray;
},
notEmpty = function() { return arguments[0].length > 0; };
Usage:
var orderedArray = posConcat(array1,array2,array3);
Sample: http://jsfiddle.net/HH9SR/

Categories