silent_coder14
silent_coder14

Reputation: 583

how to get index of duplicates in a javascript array?

I have a sorted array like this:

var a= [
    {id:"1", name:"A", address:"A"},
    {id:"2", name:"A", address:"B"},
    {id:"3", name:"A", address:"C"},
    {id:"4", name:"B", address:"A"},
    {id:"5", name:"B", address:"B"},
    {id:"6", name:"C", address:"A"},
    {id:"7", name:"C", address:"B"},
    {id:"8", name:"C", address:"C"},..

What I want to do is get the index of those duplicated 'names' like

index 0-2 => "A";
index 3-4 => "B";
index 5-7 => "C";

Or even counting those duplicates will do such as 3 for A, 2 for B, 3 for C.

        var counter = 0;
        var prev = "";
        var next = "";
        var prevLink = a[0].name;

        for (var i = 0; i < a.length; i++) { 

         if(i >= ssRow.length){
             //do nothing
        }else{        
          next  = a[i+1].name;  
        } 

        if(prev== next){
          counter++;
        }else{        
          counter = 0;
          prevLink = a[i].name;      
        }
          //play with counter variable
        }

But it's not working as expected. Is there a much better way or efficient way to do it?

Upvotes: 2

Views: 13219

Answers (7)

Roh&#236;t J&#237;ndal
Roh&#236;t J&#237;ndal

Reputation: 27192

You can use ES6 Array.from() method.

Try this it will work as per your expectation :

var a = [
    {id:"1", name:"A", address:"A"},
    {id:"2", name:"A", address:"B"},
    {id:"3", name:"A", address:"C"},
    {id:"4", name:"B", address:"A"},
    {id:"5", name:"B", address:"B"},
    {id:"6", name:"C", address:"A"},
    {id:"7", name:"C", address:"B"},
    {id:"8", name:"C", address:"C"}];

// fetch all the name property value into an array.
var nameArr = Array.from(a, x => x.name);

var obj = {};

for (var i = 0; i < nameArr.length; i++) {
    var elem = nameArr[i];

    // if we haven't seen the element yet, 
    // we have to create a new entry in the map
    if (!obj[elem]) {
        obj[elem] = [i];
    }
    else {
        if(obj[elem].indexOf(nameArr.lastIndexOf(elem)) == -1) {
          // otherwise append to the existing array
          obj[elem].push(nameArr.lastIndexOf(elem));
        }
    }
}
 
for (var i in obj) {
  console.log('index ' +obj[i].join('-')+ ' => "'+i+'"');
}

Upvotes: 1

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48337

You can do more simply using filter method in combination with forEach.

The first step is to find out the unique names from your array. This can be achieved using Set method from ES6.

var names=[...new Set(array.map(a=>a.name))];

or

UPDATE

 names=array.map(a=>a.name).filter(function (x, i, a) { 
      return a.indexOf(x) == i; 
 });

Then you should use filter method, which accepts a callback provided function , in order to get the items which have name equals to one element from names array.

var array= [
    {id:"1", name:"A", address:"A"},
    {id:"2", name:"A", address:"B"},
    {id:"3", name:"A", address:"C"},
    {id:"4", name:"B", address:"A"},
    {id:"5", name:"B", address:"B"},
    {id:"6", name:"C", address:"A"},
    {id:"7", name:"C", address:"B"},
    {id:"8", name:"C", address:"C"}];
    
var names=[...new Set(array.map(a=>a.name))];
names.forEach(function(item){
  indexes=array.map(function(item,i){
     item["index"]=i;
     return item;
  })
  .filter(a=>a.name==item)
  .map(a=>a.index);
  console.log(indexes[0]+'-'+indexes[indexes.length-1]+'->'+item+', count= '+indexes.length);
});

Upvotes: 0

AncientSwordRage
AncientSwordRage

Reputation: 7608

You could try to use the groupBy method in underscore. It doesn't do the full job of formatting it, but gets you to a good place to carry on with it.

var data = [{ id: "1", name: "A", address: "A" }, { id: "2", name: "A", address: "B" }, { id: "3", name: "A", address: "C" }, { id: "4", name: "B", address: "A" }, { id: "5", name: "B", address: "B" }, { id: "6", name: "C", address: "A" }, { id: "7", name: "C", address: "B" }, { id: "8", name: "C", address: "C" }],

groups = _.groupBy(data, 'name');
console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Upvotes: 0

pranay kumar
pranay kumar

Reputation: 404

 let dupes = {};
 const array= [
        {id:"1", name:"A", address:"A"},
        {id:"2", name:"A", address:"B"},
        {id:"3", name:"A", address:"C"},
        {id:"4", name:"B", address:"A"},
        {id:"5", name:"B", address:"B"},
        {id:"6", name:"C", address:"A"},
        {id:"7", name:"C", address:"B"},
        {id:"8", name:"C", address:"C"}];
 array.forEach((item,index) => {
   dupes[item.name] = dupes[item.name] || [];
   dupes[item.name].push(index);
 });       
 for(let name in dupes) console.log(name+'->indexes->'+dupes[name]+'->count->'+dupes[name].length)

Upvotes: 4

Nina Scholz
Nina Scholz

Reputation: 386550

You could use Array#reduce and check the predecessor if the name is not the same or at the first index, then create a new array with the index information.

var data = [{ id: "1", name: "A", address: "A" }, { id: "2", name: "A", address: "B" }, { id: "3", name: "A", address: "C" }, { id: "4", name: "B", address: "A" }, { id: "5", name: "B", address: "B" }, { id: "6", name: "C", address: "A" }, { id: "7", name: "C", address: "B" }, { id: "8", name: "C", address: "C" }],
    groups = data.reduce(function (r, a, i, aa) {
        (!i || aa[i - 1].name !== a.name) && r.push([i, i, a.name]);
        r[r.length - 1][1] = i;
        return r;
    }, []);

console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Simple_Programmer
Simple_Programmer

Reputation: 690

For counting the duplicates, you can use Underscore.js which has a method called _.groupBy()(see this). It gives you an object of key-value pairs where keys are the value you want to check for duplication and value is the array of objects what have that key. Its like this -

  var groupedData = _.groupBy(array, function(elem){
       return elem.name; //here you can specify whichever key you want to check duplicates for
  });

  console.log(groupedData['A'].length);

Upvotes: 0

Nenad Vracar
Nenad Vracar

Reputation: 122027

You can use reduce() to return object as result with both count and start-end index for each name.

var arr = [{"id":"1","name":"A","address":"A"},{"id":"2","name":"A","address":"B"},{"id":"3","name":"A","address":"C"},{"id":"4","name":"B","address":"A"},{"id":"5","name":"B","address":"B"},{"id":"6","name":"C","address":"A"},{"id":"7","name":"C","address":"B"},{"id":"8","name":"C","address":"C"}]

var l = null;

var result = arr.reduce(function(r, e, i) {
  if (!r[e.name]) {
    l = e.name;
    r[e.name] = {
      count: 1,
      index: i.toString()
    }
  } else {
    if (arr[i + 1] && arr[i + 1].name != l || !arr[i + 1]) r[e.name].index += '-' + i;
    r[e.name].count++
  }
  return r;
}, {})

console.log(result)

Upvotes: 2

Related Questions