0

I'am pretty new to JavaScript and i have this exercise that have been bugging me for a some hours now.

I want to write a Javascript function that expects an array which could contain string and/or numbers (as well as finite levels of nested arrays of strings and/or numbers), and returns a Javascript object which shows the total number of occurences of each unique values.

Something like this

var myArray = [ 1, 2, 1, 'a', [ 'd', 5, 6 ], 'A', 2, 'b', 1, 'd' ];
var myResult = myFunction( myArray );

Then it should return something like this

yourResult = {
    1: 3,
    2: 2,
    'a': 1,
    'd': 2,
    5: 1,
    6: 1,
    'A': 1,
    'b': 1,
}

So far what i have is this. I dont know how to create the object but this is not working at all. It ads all the values in the array

Array.prototype.contains = function(v) {
for(var i = 0; i < this.length; i++) {
    if(this[i] === v) return true;
}
return false;
};

Array.prototype.unique = function() {
var arr = [];
for(var i = 0; i < this.length; i++) {
    if(this[i] instanceof Array) {
        for(var j = 0; i < this[i].length; j++){
        if (!arr.contains(this[i][j])){
            arr.push(this[i][j]);
        }
        } 
    }
    if(!arr.contains(this[i])) {
        arr.push(this[i]);
    }
}
return arr;
}

var myArray = [1,3,4,2,1,[1,2,3,6],2,3,8];
var myResult = duplicates.unique();

console.log(myResult);  
3
  • What functions have you tried? Commented May 19, 2015 at 11:19
  • I will update my post :) Commented May 19, 2015 at 11:20
  • You should in fact divide this in two functions: myArray.flatten().count(). A .unique() method would typically only remove duplicates, but not count occurences. Commented May 19, 2015 at 11:34

3 Answers 3

2

I would seperate it into 2 major problems: 1. Make the array members to be at one level (not nested). 2. Count repeats

The first one I solved with recursion, hope it's meet the requirements. The second is about counting instances..

Hope it's help

Fiddle example

var myArray = [ 1, 2, 1, 'a', [ 'd', 5, 6 ], 'A', 2, 'b', 1, 'd' ];
var myResult = myFunction( myArray );
console.log(myResult);

function myFunction(arr) {
    var r = {};
    for (var i=0 ; i < arr.length ; i++) {
        if( Object.prototype.toString.call( arr[i] ) === '[object Array]' ) {
            var sub = myFunction(arr[i]);
            for (var attrname in sub) { 
                if (r[attrname])
                    r[attrname]++;
                else {
                     r[attrname] = sub[attrname]; 
                    r[attrname] = 1;
                }
            }
        }
        else if (r[arr[i]])
            r[arr[i]]++;
        else
            r[arr[i]] = 1;
    }

    return r;
}
Sign up to request clarification or add additional context in comments.

Comments

1

An associative array is what you need to hold the result:

var associative_array={}

then you can use a function like this:

function add_to_as(value){ //Add element to the global associative array
if(associative_array[value]==undefined){
    associative_array[value]=1;
}
else{
    associative_array[value] +=1;//add one
}
}

function myFunction( mydata ){
for(var i = 0; i < mydata.length; i++) {
    if(mydata[i] instanceof Array) { //recurse on sublists if any
        myFunction(mydata[i])
    }
    else{
        add_to_as(mydata[i]);
    }
}
}
//To test the function
var myArray = [ 1, 2, 1, 'a', [ 'd', 5, 6 ], 'A', 2, 'b', 1, 'd' ];
myFunction(myArray);
console.log(associative_array);

Comments

0

Besides your code
you can put all the elements of your array to a second array containing all the elements of array and sub arrays. Then you can iterate over second array and find the occurrence of each element like this

var arr1 = [1, 2, 1, 'a', ['d', 5, 6], 'A', 2, 'b', 1, 'd'];
var arr = [];
var obj = {};

for (var i = 0; i < arr1.length; i++) {
    if (arr1[i].length == undefined || arr1[i].length == 1) {
        arr.push(arr1[i]);
    }
    else {
        for (var j = 0; j < arr1[i].length; j++) {
            arr.push(arr1[i][j]);
        }
    }
}

for (var i = 0, j = arr.length; i < j; i++) {
    if (obj[arr[i]]) {
        obj[arr[i]]++;
    }
    else {
        obj[arr[i]] = 1;
    }
}

console.log(obj);  

DEMO
Updated:In case of nested arrays

var arr2 = [1, 2, 1, 'a', ['d', 5, 6,['d', 5, 6,['d', 5, 6]]], 'A', 2, 'b', 1, 'd'];
var arr = [];
var obj = {};
function singleArray(arr1) {

    for (var i = 0; i < arr1.length; i++) {
        if (arr1[i].length == undefined || arr1[i].length == 1) {
            arr.push(arr1[i]);
        }
        else {
            singleArray(arr1[i]);
        }

    }
}
singleArray(arr2);
for (var i = 0, j = arr.length; i < j; i++) {
    if (obj[arr[i]]) {
        obj[arr[i]]++;
    }
    else {
        obj[arr[i]] = 1;
    }
}
console.log(obj);  

DEMO

1 Comment

It's supports only one level of nested array, the question define "finite levels of nested arrays"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.