javascript

Find Duplicate Element in JavaScript Array

1
2
3
4
5
6
7
function uniq(l) {
return l.filter(function (e, i) { return l.indexOf(e) === i; });
}
function findDup(l) {
return uniq(l.filter(function (e, i) { return l.indexOf(e) !== i; }));
}

Example:

1
2
> findDup([1, 2, 3, 4, 2, 5, 1, 2]);
< [2, 1]

Efficient Representation of a Sparse Array in JavaScript

I’m using an array to represent ranges of numbers. For example, in this array,

1
[1, 2, 3, 4, 15, 16, 17, 18]

there are two sequences of consequitive numbers: 1-4 and 15-18. In order to save space when serializing this array, it can be represented as ranges of numbers. For example:

1
[ [1, 4], [15, 18] ]

This function takes in an array of numbers, and returns an array of ranges:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function sparsify(l) {
var i, j, k;
var ranges = []; // [ [from, to], [from, to], ... ]
function insertNum(n) {
for (j = 0; j < ranges.length; j++) {
if (ranges[j][0] <= n && n <= ranges[j][1]) return; // already in a range
if (n === ranges[j][0] - 1) // immediately before a range
ranges[j][0] = n;
else if (n === ranges[j][1] + 1) // immediately after a range
ranges[j][1] = n;
else
continue;
for (k = 0; k < ranges.length; k++) { // merge ranges
if (j === k) continue;
// do ranges j and k overlap?
if ( (ranges[j][0] <= ranges[k][0] && ranges[k][0] <= ranges[j][1] + 1) ||
(ranges[j][0] - 1 <= ranges[k][1] && ranges[k][1] <= ranges[j][1])) {
ranges[j] = [Math.min(ranges[j][0], ranges[k][0]), Math.max(ranges[j][1], ranges[k][1])];
ranges.splice(k, 1);
break;
}
}
return;
}
ranges.push([n, n]); // not found; add new range
}
for (i = 0; i < l.length; i++)
insertNum(l[i]);
return ranges;
}

JavaScript: List Directory Contents With Apache Indexes

This can be useful if you are writing something that is entirely client-side and has to list the contents of directories on the web server. The only limitations are that:

  • the web server has to be running Apache with directory indexes enabled;
  • the directory to list has an index (e.g. there is no ‘index.html’ file in it); and
  • the directory to list has to be on the same domain as the script (browser security policies don’t allow cross site requests).
    Here is the code. It uses JQuery to make a AJAX request to the Apache directory index, and then parses it for links to the directory’s contents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
 * Returns a list of the files in 'path' to the callback:
 * cb(error, ['file1', 'file2', ...])
 */
function apacheIndexList(path, cb) {
  $.ajax({
    url: path,
    success: function(data) {
      /* Sanity check: is this an Apache directory index?
       */
      data = $('<html>').html(data);
      if($('title', data)[0].innerHTML.substr(0, 8) !==
        "Index of")
        return cb("Bad Apache directory index: " + path);
      /* Get all the hrefs after the "Parent Directory"
       * link: these are the contents of the directory.
       */
      var passedParentLink = false;
      var files = $('a', data).filter(function(i, a) {
        if(passedParentLink)
          return true;
        if(a.innerHTML.trim() === "Parent Directory")
           passedParentLink = true;
        return false;
      });
      var tidied = $(files).map(function(i, a) {
        if(a.href.substr(-1) === '/')
            return a.href.split('/').slice(-2,-1) + '/';
        return a.href.split('/').pop();
      });
      cb(null, tidied);
    },
    error: function(jqXHR, error, errorThrown) {
      cb(error);
    }
  });
}

This can be tested on the console. First define a function ls:

1
2
3
4
5
6
function ls(d) {
apacheIndexList(d, function(e, l) {
if(e) throw e;
else console.log(l);
});
}

Then try listing the contents of some directories:

1
2
3
4
5
6
7
> ls('images/')
&lt; undefined
["img1.jpg", "img2.jpg", "img3.jpg", "thumbs/"]
> ls('images/thumbs/')
&lt; undefined
["img1.jpg", "img2.jpg", "img3.jpg"]