Daniel Larsson
Daniel Larsson

Reputation: 6394

How to make Javascript array unique by attribute

What is a fast way of making a Javascript array unique by attribute?

I have an array sorted by timestamp, like this:

[
    {
        ts: 1417048100,
        release: 1.0
    },
    {
        ts: 1417046900,
        release: 1.1
    },
    {
        ts: 1417046712,
        release: 1.0
    }
]

And I want to make it unique by release number, keeping only the ones with the latest timestamp. In my example, that would mean removing the last entry since there is a newer one for that release.

Upvotes: 3

Views: 886

Answers (6)

Dalorzo
Dalorzo

Reputation: 20014

You can use Array.prototype.reduce along with Array.prototype.some like:

var items = [{ts: 1417048100,release: 1.0},{ts: 1417046900,release: 1.1},{ts: 1417046712,release: 1.0}];

var results = items.reduce(function(res, item){
var exists = res.some(function(t){ return (t.release === item.release );});        
     if (!exists){
        res.push(item);
     }
return res; },[]);
                                                                              document.body.innerHTML = '<pre>' + JSON.stringify(results) + '</pre>';

Array.prototype.some allows you to check whether or not the item exists in the array and if it does it is not included in the Array.prototype.reduce res.push(item); while processing of the array.

If you are open to use other libraries you may be interested in checking lo-dash unique:

https://lodash.com/docs#uniq

Upvotes: 0

guest271314
guest271314

Reputation: 1

Try

var arr = [
  {
    ts: 1417048100,
    release: 1.0
  },
  {
    ts: 1417046900,
    release: 1.1
  },
  {
    ts: 1417046712,
    release: 1.0
  }
]

, arr = arr.sort(function(a, b) {
  return (a.ts > b.ts) ? -1 : 1
}).filter(function(val, key) {
  return $.inArray(val.release, arr.map(function(v) {return v.release})) === key
});

    var arr = [
      {
        ts: 1417048100,
        release: 1.0
      },
      {
        ts: 1417046900,
        release: 1.1
      },
      {
        ts: 1417046712,
        release: 1.0
      }
    ]

    , arr = arr.sort(function(a, b) {
      return (a.ts > b.ts) ? -1 : 1
    }).filter(function(val, key) {
      return $.inArray(val.release, arr.map(function(v) {return v.release})) === key
    });

    $.each(arr, function(k, v) {
      $("<span>").html("release:" + v.release + ", timestamp:" + v.ts + "<br />")
      .appendTo("body")
    })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Upvotes: 0

maruthu chandrasekaran
maruthu chandrasekaran

Reputation: 168

if you can use jquery then try with grep

var releases =[
    {
    ts: 1417048100,
    release: 1.0
    },
    {
        ts: 1417046900,
        release: 1.1
    },
    {
        ts: 1417046712,
        release: 1.0
    }];

    var newRelease={
        ts: 1517046712,
        release: 1.0
    };

releases = jQuery.grep(y, function(value) {
  return value.release != newRelease.release;
});

releases.push(newRelease);

Upvotes: 0

adeneo
adeneo

Reputation: 318202

You could iterate over the array with forEach and store the release numbers in an object to make sure that any releases already iterated over are spliced out of the array.

var arr = [{
    ts: 1417048100,
    release: 1.0
},
{
    ts: 1417046900,
    release: 1.1
},
{
    ts: 1417046712,
    release: 1.0
}];

var o = {};

arr.forEach(function(x, i) {
    if (x.release in o) arr.splice(i, 1);
    o[x.release] = null; 
});

document.body.innerHTML = '<pre>' + JSON.stringify(arr, null, 4) + '</pre>';

Upvotes: 2

aarti
aarti

Reputation: 2865

Convert the array into an associative array. The keys in an associative array are unique. Example code shown in node.

→ node
> a ={ "1.0": 1417048100, "1.1": 1417046900}
{ '1.0': 1417048100,
  '1.1': 1417046900 }
> a["1.0"]
1417048100
> a["1.0"]=99999
99999
> a
{ '1.0': 99999,
  '1.1': 1417046900 }

For a better understanding read up on hashes and the blog post below may also be helpful.

http://www.javascriptkata.com/2007/03/29/how-to-use-javascript-hashes/

Upvotes: -1

gahooa
gahooa

Reputation: 137312

Convert it to a mapping, using the release as the key.

var output = {};
for(var i=0; i<input.length; i++) {
  output[input[i].release] = input[i].ts;
}

It will automatically overwrite older release keys with newer release keys.

If you need it to remain sorted, then you would need to re-convert it to a list and sort it, or filter the original list down by only the remaining output keys.

Upvotes: 1

Related Questions