Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

18.01.2017

Google
WWW CITForum.ru
С Новым годом!
2005 г.

Сортировка таблицы средствами JavaScript

Вячеслав Шуранов, JavaPortal

Достаточно часто пользователям интернет приходится сталкиваться с большим объемом информации, представленным в виде таблицы. Не менее часто требуется получить результаты в ином порядке, чем они представлены первоначально. Большинство web-мастеров решает эту проблему применением сортировки на сервере, для чего используется перезагрузка страницы. Действительно, серверные языки предоставляют гораздо больше возможностей отсортировать многомерный массив по определенному значению, чем скриптовые языки, выполняющиеся непосредственно на стороне клиента. Решение сортировать данные на стороне сервера вполне оправданно с точки зрения трудозатрат программиста, так как многие серверные языки имеют встроенные функции сортировки многомерных массивов, и поэтому не требуется вдумываться в алгоритмы сортировки, что-то изобретать или перестраивать алгоритм под свои нужды. Но все-таки такое решение не оправдано, если подходить к этой проблеме с точки зрения пользователя. Вначале посетителю сайта требуется дождаться достаточно длительной загрузки страницы, просмотреть результаты, нажать на кнопку "Отсортировать" и... опять дожидаться, пока сервер закончит работу и вернет результат. Такие множественные перезагрузки страницы никак не способствуют популярности сайта у посетителя. В конце-концов, устав дожидаться очередной загрузки страницы, или испугавшись лишнего траффика, он покинет сайт в поисках более лояльного к нему web-мастера. Решением данной проблемы, а именно эффективной сортировки данных и формирования результирующей таблицы, я и предлагаю заняться в этой статье. А в качестве примера данных будет выступать информация о книгах: дата написания, название книги и ее автор.

Начнем с функции fillArray, которая и будет эмулировать многомерный массив, а вернее создать класс-объект с членами - данными многомерного массива. Приведем ее код:

Листинг 1:

1   function fillArray( years, books, authors ) {		
2    authors = upCs( authors, " " );
3    authors = upCs( authors, "-" );
4    books = upCs( books, "" );
5
6    this.years = years;
7    this.yweight = weight( years );
8    this.books = books;
9    this.bweight = weight( books );
10   this.authors = authors;
11   this.aweight = weight( authors );
12 }

Разберем данные по строкам. Во второй строке вызывается функция upCs с параметром authors и пробелом в качестве второго параметра. Функция upCs создает заглавные буквы в начале строки и перед каждым вхождением второго аргумента. Эта функция была написана исключительно потому, что не все обрабатывают данные должным образом и вполне могут написать имя писателя, например, с маленькой буквы. Применение такой функции устраняет возможную ошибку программиста в заполнении массива данными, а также позволяет быть уверенным, что в функции сортировки не будет неверного сравнения заглавных букв со строчными. Впрочем, если вы уверены в том, что данные будут занесены верно, можете убрать вызовы этой функции:

Листинг 2:

1  function upCs( str, param ) {    
2   var tmpStr = str.substring( 0, 1 ).toUpperCase() + str.substring( 1 );
3   if( !param )
4    return tmpStr;
5   var separator = tmpStr.indexOf( param );
6   var retStr = tmpStr;
7   if( separator != -1 )
8    retStr = tmpStr.substring( 0, separator );
9
10  while( separator != -1 ) {	 
11   tmpStr = tmpStr.substr( separator + 1, 1 ).toUpperCase() + tmpStr.substring( separator + 2 );
12   separator = tmpStr.indexOf( param );
13   if( separator != -1 )
14     retStr += param + tmpStr.substring( 0, separator );
15   else
16    retStr += param + tmpStr;
17  }
18
19  return retStr;	
20 }

Эта же функция, вызванная с пустым вторым аргументом, возвращает результат с заглавной буквой только в начале строки. Теперь обратимся к строке 7, листинга 1. Здесь вызывается функция weight, которая возвращает числовые значения каждого символа аргумента в виде массива. Для чего я ее написал? Дело в том, что коды символов русского алфавита в браузере идут последовательно, кроме кода символа буквы "ё". Код этого символа больше кодов символов остального алфавита, поэтому приходится присваивать такое "весовое" значение этому символу, которое соответствовало бы его позиции в алфавите. Вот код этой функции:

Листинг 3:

1  function weight( str ) {
2   var retArray = new Array();
3	 
4   for( var i = 0; i < str.length; i++ ) {
5    var tmp = str.charCodeAt( i );
6    if( tmp >= 1046 && tmp < 1078 )
7     tmp++;
8    else if( tmp == 1025 )
9     tmp = 1046;
10   else if( tmp >= 1078 )
11    tmp++;
12   else if( tmp == 1105 )
13    tmp = 1078;
14   retArray[ i ] = tmp;
15  }
16
17  return retArray;
18 }

Ну что же, функции, необходимые для создания нашего многомерного массива готовы. Осталось создать массив и заполнить его данными:

Листинг 4:

1  var txt = [];
2  txt[ 0 ] = new fillArray( "1959", "фрейд", "сартр жан-поль" );
3  txt[ 1 ] = new fillArray( "1940", "подростки", "сэлинджер джером" );
4  txt[ 2 ] = new fillArray( "1946", "пена дней", "виан борис" );
5  txt[ 3 ] = new fillArray( "1948", "осадное положение", "камю альбер" );
6  txt[ 4 ] = new fillArray( "1899", "об иноческой жизни", "рильке райнер мария" );
7  txt[ 5 ] = new fillArray( "1849", "аннабель Ли", "по эдгар" );
8  txt[ 6 ] = new fillArray( "1917", "дагон", "лавкрафт говард" );
9  txt[ 7 ] = new fillArray( "1915", "процесс", "кафка франц" );
10 txt[ 8 ] = new fillArray( "1989", "египет Рамсесов", "монтэ пьер" );
11 txt[ 9 ] = new fillArray( "1932", "мастер и Маргарита", "булгаков михаил" );

Обратить внимание стоит лишь на то, что года, когда были написаны книги, я передаю в функцию в качестве строкового параметра, а не числового. Делается это для того, чтобы не писать несколько функций сортировки.

Насколько быстр такой метод заполнения массива? На компьютере со средней производительностью загрузка 1000 элементов происходит за 450 - 800 миллисекунд. Но поскольку пользователь будет получать массив такого размера не сразу, а по частям, и размер этих частей будет сильно зависеть от скорости его соединения с интернет, то время, затрачиваемое на создание элемента массива и определение весовых значений его данных, будет незаметно пользователю.

Я подошел к самой интересной части данной статьи, а именно - к непосредственной работе с данными. В качестве функции сортировки данных я выбрал сортировку Хоара, которая, как мне кажется, наиболее соответствует поставленной задаче в начале статьи. Вот ее код, нюансы которого рассмотрю несколько более подробно.

Листинг 5 :

1  function quickSort( l, h, type ) {
2   var low = l;
3   var high = h;	
4   var rt = eval( "txt[ " + Math.round( ( l + h ) / 2 ) + " ]" );
5   var middle = new fillArray( rt.years, rt.books, rt.authors );
6	
7   do {
8	
9    while( isLow( eval( "txt[ " + low + " ]" ), middle, type ) )
10    low++;
11
12   while( isLow( middle, eval( "txt[ " + high + " ]" ), type ) )
13    high--;
14
15   if( low <= high ) {
16    var temp = txt[ low ];
17    txt[ low++ ] = txt[ high ]
18    txt[ high-- ] = temp;
19    }
20   } while( low <= high );
21
22   if( l < high )
23    quickSort( l, high, type );
24   if( low < h )
25    quickSort( low, h, type );
26 }

В листинге 5 приведена классическая сортировка Хоара, но с небольшими модификациями. На этих модификациях я и хочу обратить внимание прежде всего. ИтаК, посмотрим на строки 4-5. Здесь создается новый элемент на основании данных элемента массива, который берется как среднее значение между границами цикла сортировки. Почему пришлось внести такую модификацию? Почему нельзя было написать классически, как и положено в сортировке Хоара: var middle = eval( "txt[ " + Math.round( ( l + h ) / 2 ) + " ]" );? Дело в том, что здесь не получено значения элемента массива, как в классической сортировке, а есть только ссылка на него (хотя слово ссылка здесь не совсем уместно). При таком подходе дальнейшие действия теряют смысл. Немного отклонюсь от темы моей статьи и разъясню этот момент. Приведу следующий листинг:

Листинг 6 :

1  function cls() {
2   this.member = "value";
3  }
4   
5  var x = new cls();
6  var y = x;
7  alert( "x.member = " + x.member + ", y.member = " + y.member );
8  x.member = "new value";
9  alert( "x.member = " + x.member + ", y.member = " + y.member );

Что происходит после того, как на восьмой строке было присвоено члену класса новое значение? Изменится ли только значение в переменной x? Нет, изменится значение в обеих переменных. Дело в том, что присваивания значения созданного пользовательского класса не происходит. Попробую провести похожую аналогию со ссылками в языке С++. Я не получу автономного значения, которое было бы независимо от оригинала. А получу своего рода ссылку на значение, которое подвержено изменениям из оригинальной переменной. Такая ссылка разрушает всю семантику сортировки Хоара, поскольку алгоритм требует сравнения в процессе сортировки с опорным значением середины диапазона элементов, а сам алгоритм в процессе работы может заменять значение, находящееся по адресу опорного элемента другим значением. Именно поэтому мне пришлось создать отдельное значение через оператор new. Конечно, это влечет дополнительные затраты процессорного времени на повторное определение "весовых" значений данных, но эти затраты достаточно минимальны. Впрочем, если у вас есть желание, вы можете модифицировать функцию fillArray так, чтобы она принимала шесть аргументов. В качестве трех последних аргументов можно заносить уже полученные ранее данные о "весовом" значении членов массива.

Итак, я выяснил зачем требуется создавать новый элемент в сортировке Хоара. Перейду теперь к строкам 9 и 12. Здесь в качестве сравнения значений элементов вызывается функция isLow, которая принимает в качестве аргументов два объекта для сравнения и третий аргумент - имя члена класса, по которому производится сортировка (внимательный читатель уже заметил этот третий непонятный аргумент в алгоритме Хоара). Приведу эту функцию сравнения:

Листинг 7 :

1  function isLow( low, high, type ) {
2    var len1 = low[ type ].length;
3    var len2 = high[ type ].length;
4    var length = len1 < len2 ? len1 : len2;
5	
6    for( var i = 0; i < length; i++ ) {
7     var str1 = low[ type ][ i ];
8     var str2 = high[ type ][ i ];
9     if( str1 < str2 )
10     return true;
11    if( str1 > str2 )
12     return false;
13   }
14	
15   if( len1 < len2 )
16    return true;
17   return false;
18  }

Как видите, кроме принципа работы с самими элементами, ничего необычного не происходит. Здесь для обращения к членам класса используются квадратные скобки, как в массиве. Подробнее о таком способе работы с пользовательскими объектами можно прочитать у Дмитрия Котерова на http://dklab.ru в статье "Маленькие хитрости JavaScript". Упомяну лишь то, что касается непосредственно работы нашей функции. Следует обратить внимание на строки 7 - 8. Здесь используется необычный способ адресации элемента. Предположу, что значение аргумента type равно "yweight", то есть хочу отсортировать по годам и обращаюсь к массиву-члену класса, который содержит данные о "весовом" значении строки с числом года. То есть фактически я буду обращаться так: low.yweight[ i ]. В этой функции больше никаких сложностей не вижу, поэтому пойду дальше.

Во всем остальном функция сортировки полностью соответствует своему классическому варианту, о реализации которого написано большое количество статей, поэтому больше никаких вопросов, касающихся этой функции, здесь рассматриваться не будет. Я же перейду к заключающей части своей статьи и рассмотрю функцию создания таблицы на основе DOM (Document Object Model), а также функции выбора сортировки. Сразу возьму код, который должен быть между тегами body:

Листинг 8 :

1  <table id="table">
2   <tr>
3    <td><a href="javascript:allocator( 'yweight' )">Год</a></td>
4    <td><a href="javascript:allocator( 'bweight' )">Книга</a></td>
5    <td><a href="javascript:allocator( 'aweight' )">Автор</a></td>
6   </tr>
7   <tbody id="tablebody"></tbody>
8  </table>
  

Здесь нет ничего сложного: в таблице присутствует аттрибут id = "table", чтобы из функции можно было обратиться к этому узлу. Также присутствуют строка с именами колонок и вызовом функции выбора сортировки и tbody с id = "tablebody". Зачем необходим tbody? Netscape Navigator 7.1 и вообще все браузеры на движке Gecko, а также Opera, не требуют этого элемента при динамическом создании таблицы. Но только вот этот элемент жизненно необходим, если вы хотите увидеть результат в браузере Internet Explorer. Если, создавая таблицу функциями DOM, вы пропустите создание такого элемента, то результата не увидите. Как создается таблица? Вот эта функция:

  
Листинг 9 :

1  function createTable( cStart, cType, cSize, cChange ) {
2   var tabbd = document.getElementById( "tablebody" );
3
4   if( !tabbd ) {
5    var table = document.getElementById( "table" );
6    var tbody = document.createElement( "tbody" );
7    tbody.id = "tablebody";
8    table.appendChild( tbody );
9    tabbd = document.getElementById( "tablebody" );
10  }
11    
12  while( tabbd.hasChildNodes() ) {
13   var tmp = tabbd.childNodes[ 0 ];
14   tabbd.removeChild( tmp );
15  }
16      
17  for( var counter = cStart; eval( counter + cType + cSize ); eval( "counter" + cChange ) ) {
18   var tr = document.createElement( "tr" );
19	
20   var td = document.createElement( "td" );
21   var tdtxt = document.createTextNode( txt[ counter ].years );
22   td.appendChild( tdtxt );
23   tr.appendChild( td );
24   td = document.createElement( "td" );
25   tdtxt = document.createTextNode( txt[ counter ].books );
26   td.appendChild( tdtxt );
27   tr.appendChild( td );
28   td = document.createElement( "td" );
29   tdtxt = document.createTextNode( txt[ counter ].authors );
30   td.appendChild( tdtxt );
31   tr.appendChild( td );
32   tabbd.appendChild( tr );	
33  }
34 }

Целью этой статьи не является объяснение основ DOM. Поэтому я остановлюсь только на наиболее важном моменте - необычном условии цикла for. Итак, createTable принимает четыре аргумента. Первый из них (cStart) - определяет значение счетчика в цикле for. Второй (cType) - тип сравнения, то есть значения ">", "<" и т.д. Третий аргумент ( cSize ) определяет значение, при сравнении с которым прекращается цикл. Четвертое же значение (cChange) может становиться инкрементом или декрементом, в зависимости от требования сортировки. Желательно подробно разобраться в этой строке кода, она достаточно важна. Без этих четырех аргументов пришлось бы писать несколько отдельных функций, которые бы различались только в этой строке. Этот прием достаточно удобный для общего применения, и я не исключаю возможности, что вы захотите его использовать в своих функциях.

Осталась последняя функции - allocator, которая, собственно, и управляет всеми сортировками и созданием таблицы.

  
Листинг 10 :

1  function allocator( arg ) {
2  
3   if( flag == arg ) {
4    if( sorted == "up" ) {
5     createTable( 0, "<", txt.length, "++" );
6     sorted = "down";
7    } else {
8     createTable( txt.length - 1, ">=", 0, "--" );
9     sorted = "up";
10   }	 
11   return;
12  }
13		
14  quickSort( 0, txt.length - 1, arg );	
15  createTable( 0, "<", txt.length, "++" );	
16  flag = arg;   
17 }

Зачем сортировать повторно, если сортировка уже проводилась, а пользователь желает видеть то же самое, но в обратном порядке? Достаточно вывести значения массива в обратном порядке. Эта функция вызывает функцию сортировки только в том случае, если пользователь желает отсортировать по другому критерию. Для этого введены глобальные переменные - flag и sorted. Для лучшего понимая работы функции createTable рекомендую подробно разобраться в аргументах вызова этой функции внутри функции allocator. Достаточно хорошо можно понять суть работы, если использовать какой-нибудь отладчик, например, Microsoft Visual Inter Dev.

На этом считаю статью законченной. Если вы следили внимательно за создаваемым кодом, у вас должна получиться приблизительно такая страница:


<html>
 <head>
  <title>Сортировка таблицы средствами JavaScript</title>
  <meta http-equiv="Content-type" content="text/html; charset=Windows-1251">
  <script language="JavaScript" type="text/javascript">   
   var txt = [];
   var flag;
   var sorted;
   
   function upCs( str, param ) {    
    var tmpStr = str.substring( 0, 1 ).toUpperCase() + str.substring( 1 );
    if( !param )
     return tmpStr;
    var separator = tmpStr.indexOf( param );
    var retStr = tmpStr;
    if( separator != -1 )
     retStr = tmpStr.substring( 0, separator );

    while( separator != -1 ) {	 
     tmpStr = tmpStr.substr( separator + 1, 1 ).toUpperCase() + tmpStr.substring( separator + 2 );
     separator = tmpStr.indexOf( param );
     if( separator != -1 )
      retStr += param + tmpStr.substring( 0, separator );
     else
      retStr += param + tmpStr;
    }

    return retStr;	
   }

   function weight( str ) {
    var retArray = [];
	 
    for( var i = 0; i < str.length; i++ ) {
     var tmp = str.charCodeAt( i );
     if( tmp >= 1046 && tmp < 1078 )
      tmp++;
     else if( tmp == 1025 )
      tmp = 1046;
     else if( tmp >= 1078 )
      tmp++;
     else if( tmp == 1105 )
      tmp = 1078;
     retArray[ i ] = tmp;
    }

    return retArray;
   }

   function fillArray( years, books, authors ) {		
    authors = upCs( authors, " " );
    authors = upCs( authors, "-" );
    books = upCs( books, "" );

    this.years = years;
    this.yweight = weight( years );
    this.books = books;
    this.bweight = weight( books );
    this.authors = authors;
    this.aweight = weight( authors );
   }
   
   function isLow( low, high, type ) {
    var len1 = low[ type ].length;
    var len2 = high[ type ].length;
    var length = len1 < len2 ? len1 : len2;
	
    for( var i = 0; i < length; i++ ) {
     var str1 = low[ type ][ i ];
     var str2 = high[ type ][ i ];
     if( str1 < str2 )
      return true;
     if( str1 > str2 )
      return false;
    }
	
    if( len1 < len2 )
     return true;
    return false;
   }
   
   function quickSort( l, h, type ) {
    var low = l;
    var high = h;	
    var rt = eval( "txt[ " + Math.round( ( l + h ) / 2 ) + " ]" );
    var middle = new fillArray( rt.years, rt.books, rt.authors );
	
    do {
	
     while( isLow( eval( "txt[ " + low + " ]" ), middle, type ) )
      low++;

     while( isLow( middle, eval( "txt[ " + high + " ]" ), type ) )
      high--;

     if( low <= high ) {
      var temp = txt[ low ];
      txt[ low++ ] = txt[ high ]
      txt[ high-- ] = temp;
     }
    } while( low <= high );

    if( l < high )
     quickSort( l, high, type );
    if( low < h )
     quickSort( low, h, type );
   }


   txt[ 0 ] = new fillArray( "1959", "фрейд", "сартр жан-поль" );
   txt[ 1 ] = new fillArray( "1940", "подростки", "сэлинджер джером" );
   txt[ 2 ] = new fillArray( "1946", "пена дней", "виан борис" );
   txt[ 3 ] = new fillArray( "1948", "осадное положение", "камю альбер" );
   txt[ 4 ] = new fillArray( "1899", "об иноческой жизни", "рильке райнер мария" );
   txt[ 5 ] = new fillArray( "1849", "аннабель Ли", "по эдгар" );
   txt[ 6 ] = new fillArray( "1917", "дагон", "лавкрафт говард" );
   txt[ 7 ] = new fillArray( "1915", "процесс", "кафка франц" );
   txt[ 8 ] = new fillArray( "1989", "египет Рамсесов", "монтэ пьер" );
   txt[ 9 ] = new fillArray( "1932", "мастер и Маргарита", "булгаков михаил" );  


  function createTable( cStart, cType, cSize, cChange ) {
   var tabbd = document.getElementById( "tablebody" );

   if( !tabbd ) {
    var table = document.getElementById( "table" );
    var tbody = document.createElement( "tbody" );
    tbody.id = "tablebody";
    table.appendChild( tbody );
    tabbd = document.getElementById( "tablebody" );
   }
   
   while( tabbd.hasChildNodes() ) {
    var tmp = tabbd.childNodes[ 0 ];
    tabbd.removeChild( tmp );
   }
      
      
   for( var counter = cStart; eval( counter + cType + cSize ); eval( "counter" + cChange ) ) {
    var tr = document.createElement( "tr" );
	
    var td = document.createElement( "td" );
    var tdtxt = document.createTextNode( txt[ counter ].years );
    td.appendChild( tdtxt );
    tr.appendChild( td );
    td = document.createElement( "td" );
    tdtxt = document.createTextNode( txt[ counter ].books );
    td.appendChild( tdtxt );
    tr.appendChild( td );
    td = document.createElement( "td" );
    tdtxt = document.createTextNode( txt[ counter ].authors );
    td.appendChild( tdtxt );
    tr.appendChild( td );
    tabbd.appendChild( tr );	
   }
  }
  
  function allocator( arg ) {
  
    if( flag == arg ) {
     if( sorted == "up" ) {
      createTable( 0, "<", txt.length, "++" );
      sorted = "down";
     } else {
      createTable( txt.length - 1, ">=", 0, "--" );
      sorted = "up";
     }	 
     return;
    }
		
    quickSort( 0, txt.length - 1, arg );	
    createTable( 0, "<", txt.length, "++" );	
    flag = arg;   
  }

  </script>
 </head>
 <body>
 
  <table border="1" id="table">
   <tr>
    <td><a href="javascript:allocator( 'yweight' )">Год</a></td>
    <td><a href="javascript:allocator( 'bweight' )">Книга</a></td>
    <td><a href="javascript:allocator( 'aweight' )">Автор</a></td>
   </tr>
   <tbody id="tablebody"></tbody>
  </table>

 <script language="JavaScript" type="text/javascript">
  createTable( 0, "<", txt.length, "++" );
 </script>
  
 </body>
</html>

Если будут вопросы, пожелания или просто настроение - пишите на e-mail: mailto:texadmin@javaportal.ru

Размещение рекламы — тел. +7 495 4119920, ICQ 232284597

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 4119920, ICQ 232284597 Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2007 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...