C#: List> в DataGrid

Когда-то List<> скидывали в Data­Grid вот так:

dataGridView.DataSource = null;
dataGridView.DataSource = list;

Но увы — если загружать list таким образом, в ViST2008 мы будем получать Index­Out­OfRange­Ex­cep­tion каждый раз, когда попытаемся его выделить. 🙁

Поэтому надо привязывать Bind­ingList, который умеет обновляться автоматически. А обновлять только ширину колонок:

dataGridView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);

JavaScript: Случайные элементы массива

Родилось из C#-овой, но на JavaScript наглядней.

Нужно выбрать из массива N случайных элементов. Как это сделать быстро?

Если длина массива <= N — это очевидно. А если нет? Сначала склонируем массив:

Object.prototype.clone = function() {
var newObj = (this instanceof Array) ? [] : {};
for (i in this) {
  if (i == 'clone') continue;
  newObj[i] = (this[i] && typeof this[i] == "object") ? this[i].clone() : this[i];
  return newObj;
};

Потом создадим новый массив и скопируем в него нужное число элементов, а из оригинала удалим:

function selectRemoveAdd(arr, max)
{
 var arrLength = arr.length;
 if(max >= arrLength)
  return arr.clone();
 var newArray = [];
 var cloneArray = arr.clone();
 var i = 0, newPos = 0;
 while(i++ < max)
 {
  newPos = getRandom(arrLength);
  newArray.push(cloneArray[newPos]);
  cloneArray.splice(newPos, 1);
  arrLength--;
 }
 return newArray;
}

Такой вариант обычно предлагают на форумах. Но зачем создавать ещё одни массив? Можно взять исходный и удалить всё лишнее:

var arrLength = arr.length;
 if(max >= arrLength)
  return arr.clone();
 var newArray = arr.clone();
 while(arrLength-- > max)
  newArray.splice(getRandom(arrLength), 1);
 return newArray;

Какой вариант быстрее? Правильный ответ, что быстрее оба, но по-разному. Если N меньше arr.length / 2, то первый, если больше — то второй. Поэтому самый красивый и правильный способ — это:

function selectRemoveOnly(arr, max)
{
 var arrLength = arr.length;
 var newArray = arr.clone();
 while(arrLength-- > max)
   newArray.splice(getRandom(arrLength), 1);
 return newArray;
}
function selectRemoveAdd(arr, max)
{
 var arrLength = arr.length;
 var newArray = [];
 var cloneArray = arr.clone();
 var i = 0, newPos = 0;
 while(i++ < max)
 {
  newPos = getRandom(arrLength);
  newArray.push(cloneArray[newPos]);
  cloneArray.splice(newPos, 1);
  arrLength--;
 }
 return newArray;
}
function selectOptimised(arr, max)
{
 if(max >= arr.Length)
  return arr.clone();
 if(max <= arr.length / 2)
  return selectRemoveAdd(arr, max);
 else
  return selectRemoveOnly(arr, max);
}

И работать будет просто замечательно:

JavaScript: Объекты и необъекты

Говорят, во всём семействе ECMAScript все переменные — псевдообъекты.

Так вот, это неправда.

В JavaScript, например, всего 6 типов объектов:

null, unde­fined, num­ber, string, boolean и object

а значит, записать в числовую переменную новое свойство — нельзя.

Вызывая оператор “.” для num­ber, string, boolean мы просто создаём ещё один object, который получает новое свйоство, а потом записывается в никуда. Правило конвертации простое:

  • если присвоили object — оставляем как есть
  • если присвоили unde­fined, кидаем excep­tion
  • во всех прочих случаях — new Number(input), new String(input) или new Boolean(input)

JavaScript: быстрый floor и приведение объектов

Чудесное от Михаила Барановского:

В JavaScript можно писать через степень:

var a = 120000; // make it shorter?
var a = 12e4;

 

var a = Math.floor(b);
// если b всегда > 0, можно сократить до:
var a = ~~b;

Легко получать текущую дату:

var date = +new Date;

Это работает, потому что + дёргает val­ue­of.

var a = new Boolean(false); // how to quickly check if (a)?
alert(typeof a); // "object"
alert(!!a); // always true, because a is an object
alert(!!+a);
// right result, because "+" is calling valueOf
// method and convert result to number "0..1"
alert(a>0); // even shorter

Checkbox в Chrome и Safari

В браузерах, основанных на WebKit, иногда портятся check­box-ы. Девид Уолш описал проблему и дал великолепное решение:

.checkboxList li { /* ..or whatever the parent is */
  line-height: 20px;
}

JavaScript: быстрые циклы

length в JavaScript — штука медленная. Это очень хорошо видно по скорости выполнения циклов. Вовремя заменив for на while, можно получить выигрыш в производительности в 7 раз.

В умелых руках циклы JavaScript прекрасно заменяют друг друга. А значит, есть повод дополнить старый постинг о среднем арифметическом.

var digitRegEx=/^-?d+([,.]d+)?$/g;
function arithmeticMean() {
  var len = arguments.length, i = len, finalSum = 0;
  (!i) && return 0;
  while (i--)
    if (digitRegEx.test(arguments[i]))
      finalSum += parseFloat(arguments[i]);
  return (len) ? finalSum / len : 0;
}

Кстати, как народная, так и более-менее проектная реализация всяких дополнительных функций для IE грешат for по lenght и ужасающе медленным trim(). Если руки дойдут — надо бу исправить.

JavaScript: быстрый парсинг числа

Как вы думаете, как быстрее парсить число с плавающей точкой — вот так:

function isNumber(n) {
    if (n == null) return null;
    var num_parsed = parseFloat(n);
    return (!isNaN(num_parsed) && isFinite(n)) ?  true : false;
}

Или так (reg­Exp немного исправлен по сравнению с примером с суммой, чтобы уважить сербов):

var digitRegEx=/^-?d+([,.](d+)?)?$/g;
function isNumberRegExp(n) {
    return digitRegEx.test(n);
}

По идее, reg­Exp должен работать медленней. А на самом деле скорость почти одинакова. Такие дела.