3

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.

1
  • One way could be to sort by release and ts and then filter, keeping only the first object in a sequence of objects with the same release. Commented Dec 1, 2014 at 18:32

6 Answers 6

2

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>';

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

0

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);

2 Comments

You need to compare value.release to newRelease.release. Plus, this doesn't remove the entry if it is newer than what you compare against.
i assumed the new ts will be greater than the old one, if not the OP should check converting the ts to js datetime object
0

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>

Comments

0

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

Comments

-1

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/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.