Reputation: 583
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
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
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
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
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
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
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
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