Javascript. Индексирование массивов

Очень часто возникают задачи связанные с частым обращением к тем или иным массивам. Есть различные алгоритмы, позволяющие уменьшить время обращения к определенным элементам в массиве, но можно поступить и следующим образом: реализовать возможность индексирования массива по значениям, по которым в дальнейшем можно быстро обращаться к массиву имея на руках объект индексов

Array.prototype.createIndex = function (byValue) {
    var self = this, indexes = {};
if (typeof byValue !== 'function')
byValue = function (value) {return value};
for (var index = 0, len = self.length, value; index < len; index++) {
value = byValue(self[index]);
(indexes[value] || (indexes[value] = [])).push(index);
}
return indexes;
};

var array1 = ['one', 'two', 'three', 'four', 'two'];
var Array1Indexes = array1.createIndex();
console.log(Array1Indexes);

На выходе:

  four:  [3],
  one:   [0],
  three: [2],
  two:   [1, 4]
}

var array2 = [{id: 51, value: 10}, {id: 10, value: 11}, {id: 2, value: 12}, {id: 152, value: 13}, {id: 30, value: 14}];
var Array2Indexes = array2.createIndex(function (item) {return item.id});
console.log(Array2Indexes);

На выходе:

  2:   [2],
  10:  [1],
  30:  [4],
  51:  [0],
  152: [3]
 

Javascript. Large data processing

На одном из ресурсов встретил реализацию обработки больших массивов, предотвращающая подвисание браузеров.

/**
 * @param data: An array of items to process
 * @param handler: a function which processes an individual data item
 * @param callback: an optional function called when all processing is complete
 */
var processArray = function (data, handler, callback) {
var maxtime = 100; // chunk processing time
var delay = 20; // delay between processes
var queue = data.concat(); // clone original array

 var processor = function () {
  var endtime = +new Date() + maxtime;

  do {
     handler(queue.shift());
  } while (queue.length > 0 && endtime > +new Date());

   if (queue.length > 0)
     setTimeout(processor, delay);
   else
     if (callback) callback();
 };
 setTimeout(processor, delay);
};

// testing...

var data = [];

for (var i = 1, str = 'ch'; i <= 10000; i++)
data.push(str + i);

var handler = function (item) {
console.log(item);
};

var callback = function () {
console.log('end processing');
};
processArray(data, handler, callback);


На выходе:


ch1
ch2
ch3
...
ch9997
ch9998
ch9999
ch10000
end processing


При необходимости можно засунуть в прототип:


Array.prototype.process = function (handler, callback) {
if (typeof handler !== 'function')
throw new Error("Not given handler function");

if (typeof callback !== 'function')
callback = function () {};

var maxtime = 100, // время обработки блока
delay = 20; // временная задержка между обработками

var queue = this.concat(); // копия текущего массива

var processor = function () {
var endtime = +new Date() + maxtime;

do {
handler(queue.shift());
} while (queue.length > 0 && endtime > +new Date());

if (queue.length > 0)
setTimeout(processor, delay);
else
if (callback) callback();
};

setTimeout(processor, delay); 
};

Javascript. mod and div functions

// modulo
var mod = function (a, b) {
    return a % b;
}

// integer division
var div = function (a, b) {
    return (a - a % b) / b;
};


В книге Александра Шеня "Программирование: теоремы и задачи" приведен пример вычисления частного и остатка без использования данных функций

/*
* Вычисление частного q и остатка r при делении натурального (целого неотрицательного)
* числа a на целое положительное число d без использования операций mod и div.
*/
var a = 7, d = 3;

// a >= 0; d > 0
var r = a, q = 0;
// инвариант: a = q * d + r, 0 <= r
while (!(r < d)) {
    // r >= d
    r = r - d; // r >= 0
    q = q + 1;
}

console.log('r = ' + mod(a, d) + ', q = ' + div(a, d)); // r = 1, q = 2
console.log('r = ' + r + ', q = ' + q); // r = 1, q = 2

Javascript. IsNumber check

Функция isNaN() определяет является ли литерал или переменная не числовым значением (NaN) или нет.

var validator = {
isNumber: function (x) {
   return !isNaN(x);
}
};

Но при ее использовании кроется один нюанс, если на вход валидатора дать пустую строку произвольной длины, то на выходе вы получите true, то есть это число. Это особенность javascript. Дабы этого избежать можно внести небольшую правку

var utility = {
    trim: function (str) {
        return ('' + str).replace(/^\s+|\s+$/gm, '');
    }
};

var validator = {
    isNumber: function (x) {
        x = utility.trim(x);
        return x.length > 0 && !isNaN(x);
    }
};


Также стоит обратить внимание на значение NaN, так как только для него следующее условие истинно! 

var x = NaN;
x !== x; // true