简体   繁体   中英

Javascript: Find douplicated values from array with keys

Title is pretty much self explanatory...

I want to be able to find duplicated values from JavaScript array.

The array keys can be duplicated so I need to validate only the array values.

Here is an example :

var arr=[
    Ibanez:     'JoeSatriani',
    Ibanez:     'SteveVai',
    Fender:     'YngwieMalmsteen',
    Fender:     'EricJohnson',
    Gibson:     'EricJohnson',
    Takamine:   'SteveVai'
];

In that example:

the key is the guitar brand the value is the guitar player name.

So:

If there is duplicated keys (like: Ibanez or Fender ) as on that current example that is OK :-)

But

If there is duplicated values (like: EricJohnson or SteveVai ) I'm expecting to get (return) that error:

EricJohnson,SteveVai

You can't have associative arrays in Javascript. You can create an array of objects, like:

var arr=[
    {Ibanez:     'JoeSatriani'},
    {Ibanez:     'SteveVai'},
    {Fender:     'YngwieMalmsteen'},
    {Fender:     'EricJohnson'},
    {Gibson:     'EricJohnson'},
    {Takamine:   'SteveVai'}
];

Then you'll need a for...in loop to go over every object in the array, create a new array of values and check that for duplicates, which is also not very straightforward - basically you'll want to sort the array and make sure no value is the same as the one after it.

var arrayOfValues = [];

arr.forEach(function(obj){
    for(var prop in obj)
        arrayOfValues.push(obj[prop]);
});

arrayOfValues.sort(); // by default it will sort them alphabetically

arrayOfValues.forEach(function(element,index,array){
   if(array[index+1] && element==array[index+1])
     alert("Duplicate value found!");
});

First of all, object keys can not be repeated.

This means that:

({
    "Fender": "Jim",
    "Fender": "Bob"
})["Fender"]

Would simply return: "Bob".

However, I did make a code that could allow you to find duplicates in values, but as I said, the key will have to be unique:

var arr = {
    Ibanez: 'EricJohnson',
    Fender: 'YngwieMalmsteen',
    Gibson: 'EricJohnson',
    Takamine: 'SteveVai',
    "Takamine2": 'SteveVai'
};

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

var track = [];
var exists = [];
for (var val in arr) {

    if (contains(track, arr[val])) {
        exists.push(arr[val]);
    } else {
        track.push(arr[val])
    }
}

alert(exists)

You can see it working here: http://jsfiddle.net/dr09sga6/2/

As others have commented, the example array you provided isn't a valid JavaScript array. You could, however, keep a list for each guitar type:

var mapping = {
    Ibanez:     ['JoeSatriani','SteveVai'],
    Fender:     ['YngwieMalmsteen','EricJohnson']
    Gibson:     ['EricJohnson'],
    Takamine:   ['SteveVai']
];

Or a list of each guitar/musician pair:

var pairs = [
    ['Ibanez','JoeSatriani'],
    ['Ibanez','SteveVai'],
    ['Fender','YngwieMalmsteen'],
    ['Fender','EricJohnson'],
    ['Gibson','EricJohnson'],
    ['Takamine','SteveVai']
];

Your solution is going to depend on which pattern you go with. However, in the second case it can be done in one chained functional call:

pairs.map(function(e) {return e[1]})  // Discard the brand names
.sort()  // Sort by artist
.reduce(function(p,c,i,a){
  if (i>0 && a[i]==a[i-1] && !p.some(function(v) {return v == c;})) p.push(c);
  return p;
},[]);  //Return the artist names that are duplicated

http://jsfiddle.net/mkurqmqd/1/

To break that reduce call down a bit, here's the callback again:

function(p,c,i,a){
      if (i>0 
          && a[i]==a[i-1] 
          && !p.some(function(v) {
             return v == c;
          })) 
            p.push(c);
      return p;
}

reduce is going to call our callback for each element in the array, and it's going to pass the returned value for each call into the next call as the first parameter ( p ). It's useful for accumulating a list as you move across an array.

Because we're looking back at the previous item, we need to make sure we don't go out of bounds on item 0.

Then we're checking to see if this item matches the previous one in the (sorted) list.

Then we're checking (with Array.prototype.some() ) whether the value we've found is ALREADY in our list of duplicates...to avoid having duplicate duplicates!

If all of those checks pass, we add the name to our list of duplicate values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM