среда, 29 февраля 2012 г.

Какой комбинацией клавиш перейти в командную строку браузера

Переход в командную строку браузера осуществляется комбинацией Ctrl+L, Тестировал в последних версиях FireFox, Chrome, IE, Opera, Safari.

P.S. Реально позволяет более комфортнее работать.

вторник, 14 февраля 2012 г.

JavaScript. Поиск строки методом like (аналог like из MySQL)

Недавно, мне понадобилось осуществлять поиск по массиву объектов(со строковыми полями). В JavaScript, сложный поиск осуществляется с помощью регулярных выражений, для того чтобы искать в контексте объекта String, есть метод(прототип) match().

Но так как задача похожа на поиск по БД, то мне захотелось использовать синтаксис поиска MySQL функции like() - она очень удобна, когда не нужно явно применять поиск по сложному регулярному выражению. Например: поиск строк начинающихся, заканчивающихся какой-то подстрокой или включают подстроку (что совпадало с моей задачей).

Плюс ко всему - нужно уметь динамически генерировать это условие. Конечно, в JavaScript легко создать регулярное выражение из строки с помощью конструктора new RegExp(pattern, attrs), но это не так красиво как использование like. Потому я расширил прототип String этим методом. Внутри он таки использует регулярные выражения, но от программиста это скрыто, и пользоваться этим удобно и интуитивно всем кто знает SQL.

Алгоритм еще может оптимизироваться, но уже сейчас он работает довольно быстро.

String.prototype.like = function(s) {
  if(undefined==s || typeof(s)!='string') return false;

  function replacer(str, p1, p2) {
    if(p1=='\\') return p2;
    if(p2=='%') return p1+'.+';
    return p1+'\\w';
  }
  
  var pattern = "^"+s.replace(/(.|^)([%_])/gm, replacer)+'$'; 
  var re = new RegExp(pattern, 'mg');

  if(this.match(re)) return true;
  return false;
};

Пример использования:

var s = "Test string";

console.log( s.like("%ing")  ); // True
console.log( s.like("%in")   ); // False
console.log( s.like("%in_")  ); // True
console.log( s.like("Test%") ); // True
console.log( s.like("%str%") ); // True
console.log( s.like("%spr%") ); // False
console.log( s.like("%s_r%") ); // True


Для того чтобы использовать символы "%", "_" в строке поиска, их нужно экранировать двумя бэк-слешами "\\%".

среда, 8 февраля 2012 г.

JavaScript. Проверить является или нет один хеш подмножеством другого

Задача: Проверить два хеша на предмет того, является или нет, один из них подмножеством другого. Мы проверяем полное соответствие как ключей, так и значений. Порядок параметров значения иметь не должен.

Решение:
var isHashSubset = function(a, b){
  var f = true;
  for(var id in b){
    if(b.hasOwnProperty(id)){
      if(!((undefined!=a[id])&&(undefined!=b[id])&&(b[id]==a[id]))){
        f = false;
      }
    }
  }
  if(!f){
    f = true;   
    for(var id in a){
      if(a.hasOwnProperty(id)){
        if(!((undefined!=a[id])&&(undefined!=b[id])&&(b[id]==a[id]))){
          f = false;
        } 
      }    
    }
  }
  return f;
}

var x = {'key1':'val1','key2':'val2', 'key3':'val3'};
var y = {'key1':'val1','key2':'val2'};

console.log('Result:', isHashSubset(x,y) ); // TRUE
console.log('Result:', isHashSubset(y,x) ); // TRUE

var x = {'key1':'val1','key2':'val2', 'key3':'val3'};
var y = {'key1':'val1','key4':'val4'};

console.log('Result:', isHashSubset(x,y) ); // FALSE
console.log('Result:', isHashSubset(y,x) ); // FALSE


Значения null не будут учитываться, для того чтобы учитывать их также, нужно вместо условия (обоих условиях):
(!((undefined!=a[id])&&(undefined!=b[id])&&(b[id]==a[id])))

использовать:

(!((id in a)&&(id in b)&&(b[id]==a[id])))

Усовершенствованный вариант:

var isHashSubset = function(a, b, c){
  var f = true, 
      c = c || 0; // количество рекурсивных вызовов

  for(var id in b){
    if( b.hasOwnProperty(id) && !( undefined!=a[id] && undefined!=b[id] && b[id]==a[id] ) ){
      f = false;  
    }
  }
  return (!f && c == 0) ? isHashSubset(b, a, 1) : f;
}

вторник, 7 февраля 2012 г.

MySQL. Группировка по интервалам

Постановка задачи: есть таблица table(id:int, time:timestamp, val:double) в которую периодически заносятся показания некого прибора (например каждые 5 секунд).
Задача: вывести средние значения показаний прибора за определенные интервалы времени, например средние значение за каждые 60 минут

SELECT `id`, DATE_FORMAT(`time`, '%Y-%m-%d %H:%i') as `dt`, avg(val) as `value`
FROM `table`
GROUP BY `id`, time_to_sec(`time`)- time_to_sec(`time`)%(60*60)
ORDER BY `dt` DESC

Что же происходит в запросе:
мы, фактически, работаем с целочисельной арифметикой (что есть быстро). Переводим таймстамп в int, а дальше - каждое поле делим нацело на длину интервала. Отсюда вытекает, что всем записям заданного интервала будет задаваться в соответствие одно и то же целое число, по которому и проводим группировку.

Можно добавить условие на ограничение диапазона по какому-то большому отрезку времени (неделя), я думаю это не составит труда, потому и не привожу пример.

Можно использовать группировку по интервалу с помощью функции date_sub(), но в данном случае проще и читабельнее именно такой подход (мое субъективное мнение)