user6517903
user6517903

Reputation:

How to return non-repeating values in an array?

var arr = ["a", "a", "b", "b", "c", "d", "d"]

I'm looking for function that returns non-repeating element like "c" from the above example as that's the only one without duplicate.

I have searched for an hour but all the results I found online returns:

["a", "b", "c", "d"]

which is not what I want.

Example - how to push the single occurring Bond allBond to uniqueBond ?

const bondFilms = [
  { "title" : "Skyfall", "year" : 2012, "actor" : "Daniel Craig", "gross" : "$1,108,561,008" },
  { "title" : "Thunderball", "year" : 1965, "actor" : "Sean Connery", "gross" : "$1,014,941,117" },
  { "title" : "Goldfinger", "year" : 1964, "actor" : "Sean Connery", "gross" : "$912,257,512" },
  { "title" : "Live and Let Die", "year" : 1973, "actor" : "Roger Moore", "gross" : "$825,110,761" },
  { "title" : "You Only Live Twice", "year" : 1967, "actor" : "Sean Connery", "gross" : "$756,544,419" },
  { "title" : "The Spy Who Loved Me", "year" : 1977, "actor" : "Roger Moore", "gross" : "$692,713,752" },
  { "title" : "Casino Royale", "year" : 2006, "actor" : "Daniel Craig", "gross" : "$669,789,482" },
  { "title" : "Moonraker", "year" : 1979, "actor" : "Roger Moore", "gross" : "$655,872,400" },
  { "title" : "Diamonds Are Forever", "year" : 1971, "actor" : "Sean Connery", "gross" : "$648,514,469" },
  { "title" : "Quantum of Solace", "year" : 2008, "actor" : "Daniel Craig", "gross" : "$622,246,378" },
  { "title" : "From Russia with Love", "year" : 1963, "actor" : "Sean Connery", "gross" : "$576,277,964" },
  { "title" : "Die Another Day", "year" : 2002, "actor" : "Pierce Brosnan", "gross" : "$543,639,638" },
  { "title" : "Goldeneye", "year" : 1995, "actor" : "Pierce Brosnan", "gross" : "$529,548,711" },
  { "title" : "On Her Majesty's Secret Service", "year" : 1969, "actor" : "George Lazenby", "gross" : "$505,899,782" },
  { "title" : "The World is Not Enough", "year" : 1999, "actor" : "Pierce Brosnan", "gross" : "$491,617,153" },
  { "title" : "For Your Eyes Only", "year" : 1981, "actor" : "Roger Moore", "gross" : "$486,468,881" },
  { "title" : "Tomorrow Never Dies", "year" : 1997, "actor" : "Pierce Brosnan", "gross" : "$478,946,402" },
  { "title" : "The Man with the Golden Gun", "year" : 1974, "actor" : "Roger Moore", "gross" : "$448,249,281" },
  { "title" : "Dr. No", "year" : 1962, "actor" : "Sean Connery", "gross" : "$440,759,072" },
  { "title" : "Octopussy", "year" : 1983, "actor" : "Roger Moore", "gross" : "$426,244,352" },
  { "title" : "The Living Daylights", "year" : 1987, "actor" : "Timothy Dalton", "gross" : "$381,088,866" },
  { "title" : "A View to a Kill", "year" : 1985, "actor" : "Roger Moore", "gross" : "$321,172,633" },
  { "title" : "License to Kill", "year" : 1989, "actor" : "Timothy Dalton", "gross" : "$285,157,191" }
];

let uniqueBond = ""
let allBond = []
for (i = 0; i < bondFilms.length; i++) {
  allBond.push(bondFilms[i].actor)
}
console.log(allBond)

Get all unique values in a JavaScript array (remove duplicates) does not solve it as it only removes duplicates, but I want to keep uniques.

Upvotes: 1

Views: 485

Answers (9)

georg
georg

Reputation: 214959

You can use the fact that if an element occurs only once in the array, its indexOf and lastIndexOf will be the same. So

uniqueBond = bondFilms
     .map(film => film.actor)
     .filter((actor, _, actors) => actors.indexOf(actor) === actors.lastIndexOf(actor))

Applied to the abc example:

let arr = ["a", "a", "b", "b", "c", "d", "d"];

let uniq = arr.filter(x => arr.indexOf(x) === arr.lastIndexOf(x));

console.log(uniq);

Upvotes: 4

Giorgi Moniava
Giorgi Moniava

Reputation: 28654

You can do it this way:

var arr = ["a", "a", "b", "b", "c", "d", "d"];

let count={};
arr.forEach(x=>{

 if(!count[x]) count[x]=0;
 count[x]++;

})

let result = arr.filter(x=>count[x]===1);
console.log(result)

Note since we store counts in object using array value as key and since keys in JS objects are strings, this code doesn't distinguish between 5 and "5". That is it will return [1, 2] from an input of say [1, 2, 5, "5"] because it will consider 5 and "5", "same". Other than that, it should be ok.

Upvotes: 1

Ankit
Ankit

Reputation: 632

You can try the following function to get unique values. It creates a hash for counting the frequency of every element in the arr and returns the unique values with frequency equals to 1

function getUnique(arr){
  var hash = {};
  var uniques = [];
  arr.forEach(ele =>{
    if(hash[ele]){
      hash[ele] +=1
    }
    else{
      hash[ele] = 1;
    }
  });
  
  Object.keys(hash).forEach(key =>{
    if(hash[key]==1){
      uniques.push(key);
    }
  });
 
 return uniques;
 
}
var arr = ["a", "a", "b", "b", "c", "d", "d"];
console.log(getUnique(arr));

Upvotes: 0

Jonas Johansson
Jonas Johansson

Reputation: 427

I think using indexOf and lastIndexOf is the best solution. However if you for some unknown reason don't want to do that, here is my contribution with some es6 spread operators and reduce().

let a = ["1", "1", "2", "3", "3", "1"];

const uniqueItems = a.reduce((acc, item, i) => ![...a.slice(0,i), ...a.slice(i+1,a.length)].includes(item) 
  ? acc.concat([item]) 
  : acc , [])

console.log(uniqueItems);
// output: ['2']

Upvotes: 0

Sam Stephenson
Sam Stephenson

Reputation: 5190

Use indexOf and compare it to lastIndexOf

var result = [1,1,2].filter( ( x, i, array ) => array.indexOf(x) === array.lastIndexOf(x))
console.log(result)

Upvotes: 0

Pietro Martinelli
Pietro Martinelli

Reputation: 1906

You can try something like this:

var arr = ["a", "a", "b", "b", "c", "d", "d"]

var counts = arr.reduce(function(acc, curr) { return Object.assign(acc, {[curr]: (acc[curr] || 0) + 1})   }, {})

var singleOccurrences = Object.keys(counts).filter(function(k) { return counts[k] === 1})

console.log(singleOccurrences);

Explanation:

var counts = arr.reduce(function(acc, curr) { return Object.assign(acc, {[curr]: (acc[curr] || 0) + 1}) }, {}) counts the occurrences for each item of the list (returning an object, whose keys are the items - for each key, the value is the count of the occurrences)

var singleOccurrences = Object.keys(counts).filter(function(k) { return counts[k] === 1}) iterates over keys in counts and apply a filter to the list, preserving only the kyes with exactly one occurrence

I hope this can help you!

Upvotes: 0

RamKumar
RamKumar

Reputation: 126

var arr = ["a", "a", "b", "b", "c", "d", "d"]

const newtest = arr.filter((element, index, array) => {
  const temp = array.filter(x => x === element);
  if(temp.length < 2) {
    return element;
  }
})

console.log('original ---  ', arr);
console.log('final ---  ', newtest);

Upvotes: 0

antonku
antonku

Reputation: 7665

You can meet the requirement by filtering items that have the same first index and last index:

var arr = ["a", "a", "b", "b", "c", "d", "d"];
var uniq = arr.filter((item) => arr.indexOf(item) === arr.lastIndexOf(item));

console.log(uniq)

Upvotes: 0

niranjan_harpale
niranjan_harpale

Reputation: 2274

try this:

let uniqueBonds = [...new Set([...allBonds])];

Basically with Set you will get unique items and you convert them to array with Spread Operator.

Upvotes: 0

Related Questions