Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Сортировка объекта по полю в Java Script


Автор: patap 7.5.2005, 14:57
Здорово, народ.
У меня такая проблемка.
Я создал объект и заполнил его, в общем вот фрагмент проги:

Код

function comand(name,games,wins,lose,proc) {
    this.name=name
    this.games=games
    this.wins=wins
    this.lose=lose
    this.proc=proc
}

function comand_athlantic() {
var bost_m=new Array(4)
bost_m[0]='Бостон'
bost_m[1]=73
bost_m[2]=39
bost_m[3]=34
bost_m[4]=procent(bost_m[1],bost_m[2])
    athlantic[0]=new comand(bost_m[0],bost_m[1],bost_m[2],bost_m[3],bost_m[4])
..........................................................
var newy_m=new Array(4)
newy_m[0]='Нью-Йорк'
newy_m[1]=72
newy_m[2]=37
newy_m[3]=43
newy_m[4]=procent(newy_m[1],newy_m[2])
    athlantic[4]=new comand(newy_m[0],newy_m[1],newy_m[2],newy_m[3],newy_m[4])
}


теперь подскажите:
Как упорядочнить объект athlantic[] по убыванию, по полю wins?

Я делал вот так:
Код

function sort_by_wins(com) {
var a1
var mas_wins=new Array(4)
for (i=0;i<5;i++) {
mas_wins[i]=com[i].wins
document.write(mas_wins[i]+' ')
}
for (i=0;i<5;i++) {
for (j=0;j<5;j++) {
     if (mas_wins[j]<mas_wins[j+1]) {
    a1=com[j]
    com[j]=com[j+1]
    com[j+1]=a1
     }
}
}
}

в Pascal это работает без проблем, а в JavaScript начинает гнать, в чем проблема?


 ! 
 

Aliance: patap, давай будем выбирать выражения/слова. Разговаривай нормальным языком.

Автор: Aliance 8.5.2005, 00:04
Сортировка в JavaScript происходит так:
Код

elem.sort(sortByID);

function sortByID(a, b) {
// Если данные имеют тип string
// то преобразуем их в одинокавый регистр
   a = a.toLowerCase();
   b = b.toLowerCase();
   return ((a < b) ? -1 : ((a > b) ? 1 : 0));
}


Это лишь пример, нужно знать конкретнее твою задачу...

Автор: patap 8.5.2005, 12:09
мне нужно взять и сравнить все athlantic[i].wins, и упорядочнить по убыванию athlantic[i] относительно
этого поля(wins).
вот допустим заполним поля:
Код

athlantic[0].name='Бостон'
athlantic[0].games=73
athlantic[0].wins=39
athlantic[0].lose=34

athlantic[1].name='Нью-джерси'
athlantic[1].games=74
athlantic[1].wins=35
athlantic[1].lose=39

athlantic[2].name='Филадельфия'
athlantic[2].games=73
athlantic[2].wins=36
athlantic[2].lose=37

athlantic[1].name='Торонто'
athlantic[1].games=72
athlantic[1].wins=38
athlantic[1].lose=34


теперь если вывести на экран поля athlantic[i].name, будет вот такой результат

1. Бостон
2. Нью-Джерси
3. Филадельфия
4. Торонто

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

1. Бостон(wins=39)
4. Торонто(wins=38)
3. Филадельфия(wins=36)
2. Нью-Джерси(wins=35)

в общем мне нужна функция сортировки, чтобы ей передавался объект athlantic, она его переробатывала
и выдавала результат.
во, вроде все ясно, но если чего спрашивай.


Автор: Aliance 8.5.2005, 12:58
Код

athlantic.sort(sortByWin);

function sortByWin(a, b) {
   return a.wins - b.wins;
}

Автор: Sardar 8.5.2005, 15:43
patap это еще что за паскале-дельфийский код! Так извратно на JS не пишут smile
С сортировки пузырьком вообще упал smile

Пишем правильно:
Код
//описание сущности, в которой храним инфу
function Comand(name,games,wins,lose,proc) {
    this.name=name
    this.games=games
    this.wins=wins
    this.lose=lose
    this.proc=proc
}
//контейнер, который будет умно селектировать инфу
function CommandContainer() {
  this.container=[];
}
//ну и пара функций для манипуляций, придумай ещё slice, splice, push, pop...
CommandContainer.prototype.setContainer=function(cont){
  this.container=cont;
}
//собстна выборка из контейнера, возвращаем новый контейнер с упорядоченной инфой
CommandContainer.prototype.select=function(field, comparator) {
   if(this.container.length<1) return [];
   var cont=this.container.slice(0); //копия массива
   if(typeof(comparator)!="function") comp=function(a,b) { //дефолтовый компаратор
          if(typeof(a)=="string") a=a.toLowerCase();  //на случай если значения строки
       if(typeof(b)=="string") b=b.toLowerCase(); //не учитываем регистр
       return (a<b? -1: (a>b? 1: 0));   
     }
   else comp=comparator; //либо заданный компаратор
   cont.sort(function(a, b) { //сортируем
      return comp(a[field], b[field]);
   });
   var con=new CommandContainer(); //новый контейнер
   con.setContainer(cont); //в принципе можно отдать и старый, если боишся за память :)
   return con;
}

//здесь забиваем инфу
function comand_athlantic() {
 function procent(f, p) { return (p*100)/f; }

 //смотрим на синтаксис литерального массива
 data=[
   new Comand('Бостон',73,39,34,procent(73,39)), 
   //..........................................................
   new Comand('Нью-Йорк',72,37,43,procent(72,37))
  ];
  var athlantic=new CommandContainer();
  athlantic.setContainer(data);
  return athlantic;
}

//тестируем всё
var athlantic=comand_athlantic();

var resContainer=athlantic.select('lose');  //выбираем по полю lose, дефолтовый компаратор
var res=resContainer.container;

//смотрим что вышло
for(var i=0; i<res.length; i++) {
  document.write("<div style='border: 1px solid black'>");
  for(j in res[i]) {
    document.write("res["+i+"]."+j+"=<b>"+res[i][j]+"</b><br />");
  }
  document.write("</div>");
}


Собстна надеюсь что ты врубишся в приём и перестанешь думать в убогом паскалевском стиле(да не в обиду всем фанатам, просто моё ИМХО) smile

Автор: patap 9.5.2005, 23:35
Sardar
ну, дружище, спасибо! угодил так угодил!
именно то, что надо, есть конечно непонятные моменты, ну я еще <вырезано модератором>, а если что, то спрашу. ок?
а на счет паскаля ты прав. я просто только его более менее и знаю. а java script вот только начал осваивать,
тут по-ходу свой подход нужен, но со временем вкурю что к чему, язык не из сложных.
в общем спасибо тебе. удачи!


 ! 
 

Последний раз предупреждаю: используй нормальную лексику!

Автор: patap 10.5.2005, 00:58
Sardar
обоснуй пожалуйста:
1. что значит [] в этой функции

Код

function CommandContainer() {
  this.container=[];
}
или в этой строке
   if(this.container.length<1) return [];


или я так думаю что это пустой объект?

2. объясни как действует data в этой функции?
Код

function comand_athlantic() {
 function procent(f, p) { return (p*100)/f; }
 //смотрим на синтаксис литерального массива
 data=[
   new Comand('Бостон',73,39,34,procent(73,39)), 
.........................................................................................
   new Comand('Нью-Йорк',72,37,36,procent(72,37))
  ];
  var athlantic=new CommandContainer();
  athlantic.setContainer(data);
  return athlantic;
}


и еще такоя просьба: на простом примерчике объясни как действует this. а то я вроде понимаю,
но не совсем.

буду очень благодарен.

Aliance
прости дружище, я с непривычки.
буду стараться. smile

М
 

Пользуйся кнопкой Code!

Автор: Aliance 10.5.2005, 01:08
Цитата(patap @ 10.5.2005, 01:58)
на простом примерчике объясни как действует this

интересно, ты сам писал скрипт, который ты выложил выше... ведь там она использована.
Вообще, глобальная ссылка this указывает на объект (в широком смысле этого слова), от которого производится обращение.
http://forum.vingrad.ru/index.php?showtopic=50738

Цитата(patap @ 10.5.2005, 01:58)
объясни как действует data в этой функции?

это массив. что непонятно?

Цитата(patap @ 10.5.2005, 01:58)
1. что значит [] в этой функции

я так понимаю, по умолчанию это объект, а мы его делаем массивом...

Автор: Sardar 10.5.2005, 03:05
Цитата(patap @ 9.5.2005, 23:58)
1. что значит [] в этой функции

Литеральный пустой массив. Синтаксис: ['test', 'test2', 'test3'] - массив из трёх элементов.

Цитата(patap @ 9.5.2005, 23:58)
объясни как действует data в этой функции?

Это просто массив с инфой, которую ты сам забиваешь.


Цитата(patap @ 9.5.2005, 23:58)
и еще такоя просьба: на простом примерчике объясни как действует this. а то я вроде понимаю,
но не совсем.

Как в любом ООП языке this это сылка на текущий обьект, в контексте которого исполняется функция(метод). Если функцию вызываем просто как функцию, то она исполняется в контексте window.

Автор: patap 10.5.2005, 22:05
привет еще раз.
я в общем посидел подумал, поразбирал код и появились еще вопросы
я прокоментировал строки так как я это понял, если что не правильно, прошу исправить и там где заданы вопросы - дайте ответы.
если не сложно изложите в такой же форме как и я.
заранее спасибо мужики.

Код

function Comand(name,games,wins,lose,proc) {
    this.name=name
    this.games=games
    this.wins=wins
    this.lose=lose
    this.proc=proc
}

function CommandContainer() {    //создаем контейнер, который заполним данными      
  this.container=[];             //это будет поле в котором будет храниться наш массив(data)
}

CommandContainer.prototype.setContainer=function(cont){ //создаем свойство, для того, чтобы загрузить данные в контейнер
  this.container=cont;
}

CommandContainer.prototype.select=function(field, comparator) {  //field-атрибут который задает название поля, comparator-определяет тип этого поля, правильно?
   if(this.container.length<1) return [];   //для чего эта строка?
   var cont=this.container.slice(0);   //cont приймет все элементы массива
   if(typeof(comparator)!="function") comp=function(a,b) {  //проверка на то, что поле не является функцией, для чего?
          if(typeof(a)=="string") a=a.toLowerCase();  
       if(typeof(b)=="string") b=b.toLowerCase(); 
       return (a<b? -1: (a>b? 1: 0));   
     }
   else comp=comparator;  //этот момент не понятен 
   cont.sort(function(a, b) {  //что за атрибуты передаем этой функции?
      return comp(a[field], b[field]);   //что значит a[field], b[field]?
   });
   var con=new CommandContainer();   //сохраняем результат
   con.setContainer(cont); 
   return con;
}

function comand_athlantic() {        //здесь все понятно
 function procent(f, p) { return (p*100)/f; }

 data=[
   new Comand('Бостон',73,39,34,procent(73,39)), 
   new Comand('Филадельфия',73,36,37,procent(73,36)), 
   new Comand('Торонто',73,30,43,procent(73,30)), 
   new Comand('Нью-Джерси',74,35,39,procent(74,35)), 
   new Comand('Нью-Йорк',72,37,36,procent(72,37))
  ];
  var athlantic=new CommandContainer();  //создаем объект, по функции CommandContainer(), которая как бы задает структуру объекта
  athlantic.setContainer(data);          //заполняем athlantic инфой
  return athlantic;
}

var athlantic=comand_athlantic();       //athlantic будет объектом хранящим инфу

var resContainer=athlantic.select('lose');  //передаем свойству select название поля (почему lose, а не wins?), и почему при создании свойства select функция получает 2 аргумента 
var res=resContainer.container;  //и это непонятно

for(var i=0; i<res.length; i++) {
  document.write("<div style='border: 1px solid black'>");
  for(j in res[i]) {
    document.write("res["+i+"]."+j+"=<b>"+res[i][j]+"</b><br />");
  }
  document.write("</div>");
}


Автор: Sardar 11.5.2005, 15:31
Цитата(patap @ 10.5.2005, 21:05)
field-атрибут который задает название поля, comparator-определяет тип этого поля, правильно?

Не совсем, field это имя селектируемого(выбираемого) поля по которому сортируем. Comparator(compare - сравнивать) - это функция, задающая порядок сортировки по полю обьекта. Стандартный компаратор опеделён там же в функции, сортирует по возрастанию, работает со всеми типами.

Цитата(patap @ 10.5.2005, 21:05)
if(this.container.length<1) return [];   //для чего эта строка

Если контейнер пуст, то нафиг чего либо возвращать smile Собстна я ошибся вернув пустой массив, лучше:
Код
//field - ИМЯ поля по которому выбираем
//comparator - функция, задающая направление сортировки
CommandContainer.prototype.select=function(field, comparator) {
   if(this.container.length>0) {//если нам есть чего выбирать, т.е. массив не пустой
      var cont=this.container.slice(0);   //доздаём ДУБЛИКАТ массива, дабы ты в дальнейшем не убил данные, когда вернёшь их как сслку.
      //проверяем пришёл ли компаратор
      if(typeof(comparator)!="function") comp=function(a,b) { //если ты нифига не дал(второй аргумент) - то берём дефолтовый, который здесь же и написан
          if(typeof(a)=="string") a=a.toLowerCase();  //компаратор пишем по уму
          if(typeof(b)=="string") b=b.toLowerCase();  //дабы со строками без учёта регистра работал
          return (a<b? -1: (a>b? 1: 0));   
       } else comp=comparator;  //иначе берём твой компаратор, переданный вторым аргументом
      //сортируем, в параметрах передаём новую функцию, которая заюзает компаратор на конкретном поле обьекта
      cont.sort(function(a, b) {
          return comp(a[field], b[field]);   //имя поля обьекта лежит в первом аргументе(field)
      });
   } else cont=[]; //иначе возвратим пустой контейнер
   var con=new CommandContainer();   //сохраняем результат
   con.setContainer(cont); 
   return con;
}



Цитата(patap @ 10.5.2005, 21:05)
создаем объект, по функции CommandContainer(), которая как бы задает структуру объекта

Ну почти, создаём обьект юзая конструктор CommandContainer, это не просто вызов функции smile

Цитата(patap @ 10.5.2005, 21:05)
//передаем свойству select название поля (почему lose, а не wins?), и почему при создании свойства select функция получает 2 аргумента

Собстна метод select контейнера создан для выборок по заданному полю, результат отсортирован в заданном направлении. То есть пишем: container.select("wins") - выбрали и осортировали обьекты по полю wins с дефолтовым компаратором.

Цитата(patap @ 10.5.2005, 21:05)
var res=resContainer.container;  //и это непонятно

Массив с данными лежит в поле container контейнера обьектов, мы его достали.


patap вообще JS это не такой простой язык как ты думаешь, он прост для тех кто понимает что такое функциональные языки(хотя JS не функциональный язык). Если ты писал на Python, то JS тебе покажеться очень простым и удобным. Если на Java, то наделаешь много лажи, пытаясь создать иерархии "классов", хотя понятия типа/класса в JS нет. Ну а если ты кроме паскаля/C ничего не знаешь, то придётся расслабиться и выкинуть из головы все приёмы и ограничения, что ты имел раньше. В JS, можно всё, можно даже писать код, который будет изменять сам себя по требованию задачи(лямбда программирование).

Автор: Иль 8.6.2005, 15:58
О! Ничего не понимаю smile, а надо! Придется опять велосипед изобретать smile
Добавлено @ 16:03
Sardar, если получится, то можно на словах - чего тут делается, принцип.

Автор: Иль 8.6.2005, 16:32
Sardar, вот как я понял твою идею:

В Array накидываем объектов которые хотим отсортировать в нем же, но сравнивать и сортировать сами элементы сего массива нам не интересно (да и чего мы там насравниваем smile). А когда мы начинаем сортировать массив, то в функции сравнения, применяемой в .sort(функция_сравнения) сравниваем не объектные элементы массива, а именно нужные нам значения свойств этих самых объектов-элементов и чтоб получить такое задаем нужную нам функцию сравнения через анонимную функцию .sort(function(a,b){return функция_сравнения(a[нужное_свойство],b[нужное_свойство])}), причем опрашиваемое свойство получаем из контекста метода, в котором вызываем .sort(...)

Ну скажите, что это так и мне будет полная нирвана!!!
А то я тут уже до чертиков дошол (какой-то eval() мне привиделся smile)

Автор: Иль 8.6.2005, 18:52
Цитата(Sardar @ 8.5.2005, 15:43)
if(typeof(a)=="string") a=a.toLowerCase();  //на случай если значения строки
       if(typeof(b)=="string") b=b.toLowerCase(); //не учитываем регистр

Sardar, почему на "string" проверяются и "a", и "b". Как повлияет на сравнения если проверять только "a" и .toLowerCase() применять сразу к обоим?

Автор: Sardar 9.6.2005, 01:21
Цитата
Ну скажите, что это так и мне будет полная нирвана!!!

Да, это так smile
Цитата
почему на "string" проверяются и "a", и "b

Потому что в поле обьекта може лежать что угодно. Если это строка, то обычно не нужно учитывать регистр, для этого и приводим к нижнему регистру, а затем сравниваем. Если регистр важен, то эти две строчки убираем.

Автор: Иль 9.6.2005, 21:23
Ура! Sardar, супер!!! Сделал! Все так классно прыгает! Г-г-г.
Радости до ушей, аж работать не могу.

Сделал мальца не так, но подход тот же. Хотя может и так как у тебя - не то чтобы я прототипы и конструкторы не долюбливал, а только как вижу чужие имена переменных, функций и тд (запоминать, разбираться...) голова сразу стремится суть выковырять и только.
Если б не ты, ведь уже средствами JS начал .sort() реализовавать, уф.

Во, боялся забыть:
Цитата(Sardar @ 11.5.2005, 15:31)
if(this.container.length>0) {//если нам есть чего выбирать, т.е. массив не пустой

надо делать от двух (.length>1). Чего один элемент сортировать, с чем его сравнивать smile

Тк я не хочу хранить объекты в массиве, то для сортировки (вернее мне нужно только представление о ней) делаю срисовку конструктором с группы нужных объектов в сортируемый массив, те беру одно свойство объектов по которому сортируем и заодно добавляю имя, чтоб потом связать сортировку с рабочими объектами по имени и получаю маленькие объектики в элементах массива (боже, неужели это я сказал). После использую представление о сортировке (массив) и отдаю его сборщику мусора (уж не знаю, что он там с ним делает)

Sardar, чтоб мы без создателей интерфейса Array в этом случае делали? Не ругай их smile
Добавлено @ 21:27
Да, чтоб быть точным доконца, я не всегда отдаю наработанное сборщику мусора

Автор: Sardar 9.6.2005, 22:25
Цитата
Не ругай их

Не нравиться что интерфейс Dictionary (ключь=>значение) приходиться самому реализовывать. Не нравиться что нет элементарных методов map, filter, walk и других, приходиться писать самому. А ещё ты этот же Array посмотри в JS1.5 и JS1.3(долбанный ИЕ5.0). Чувство шока и обиды smile
Хорошо что все необходимое можно реализовать самому, но теряеться скорость(не критично) и увеличиваеться размер(очень плохо!).
Цитата
Да, чтоб быть точным доконца, я не всегда отдаю наработанное сборщику мусора

По любому когда нибудь ты утеряешь ссылку на значение(массив, что угодно), например при выходе из функции. Сборщик мусора незаметно приберёт всё что из телеги выпало))

В JS не говорят о сборщике мусора, это скритовый язык, автоматический сбор мусора есть понятие "само собой разумееться".

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)