Javascript: array.forEach () иногда не работает - PullRequest
0 голосов
/ 23 августа 2010

это мой фрагмент кода, где программа не входит в цикл foreach:

var ct = new Array();
ct["me"]= {"name" : "Jakub"};
ct["you"]= {"name" : "stack"};
ct.forEach(function (c){
    document.getElementById("tmp").appendChild(document.createTextNode(c));
});

Когда я меняю индексы массива со строк («я», «ты») на целые числа, это работает:

var ct = new Array();
ct[0]= {"name" : "Jakub"};
ct[1]= {"name" : "stack"};
ct.forEach(function (c){
    document.getElementById("tmp").appendChild(document.createTextNode(c));
});

Можете ли вы помочь мне реализовать решение для перебора массивов со всеми видами индексов? Моя цель - сохранить значения для заданных объектов даты.


Я использую данные для библиотеки Protovis и AFAIK ей нужен массив в качестве входных данных.

Структура данных, которую я использую в примере с protovis, более сложна, чем та, что показана выше.

В моем проекте я отправляю через JavaBean набор некоторых объектов. Эти объекты содержат среди прочего дату. Моя цель состоит в том, чтобы показать эти объекты на графике, подобном этому, представленному на веб-сайте Protovis http: // vis.stanford.edu / protovis / ex / area.html.

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

редактирование: На данный момент я изменил метод. Вместо того, чтобы хранить строки как ключи массива, я делаю следующее: Настоящим мой оригинальный фрагмент кода:
edit2 : я добавил оригинальный ввод: var result2 = {"h": { 10 "документов": [ 11 { 12 "биографические категории": [ 13], 14 «тело»: «Консервативное правительство Греции приказало провести расследование соглашения 1955 года между С.И.А. и греческими военными о создании партизанской сети для борьбы с вторжениями сил Варшавского договора в случае войны», 15 «дескрипторов»: [ 16], 17 "generalOnlineDescriptors": [ 18], 19 "гид": 0, 20 «заголовок»: «Греция исследует план партизанской войны», 21 "локация": [ 22 "ГРЕЦИЯ" 23], 24 "имена": [ 25], 26 "onlineDescriptors": [ 27], 28 "onlineLocations": [ 29], 30 "Интернет-организации": [ 31], 32 "OnlinePeople": [ 33], 34 "onlineTitles": [ 35], 36 "организаций": [ 37], 38 "человек": [ 39], 40 "публикация": "1990-11-21 00: 00: 00.0 СЕТ", 41 "sourceFile": "0402635.xml", 42 "Таксономические классификаторы": [ 43], 44 "названия": [ 45], 46 "typesOfMaterial": [ 47], 48 "оценка": 0,80242133 49},


var resultTmp = new Array();
var i = 0;
var averageScore = 0; 

var startDate = new Date();
var endDate = new Date(1700, 01, 01);
var docDate;
var actDate;

var tlk = new Array();
var av = 0;
var d = new Object();

result2.h.documents.forEach(function(c) {
    averageScore += c.score;
  if(typeof(c.publicationDate) != "undefined"){
    docDate = c.publicationDate.split("-");
    actDate = new Date(docDate[0], docDate[1]-1, docDate[2].split(" ")[0]);
    if(actDate  endDate){
        endDate = actDate;
    }
    if(defined(tlk[actDate])){
        av = tlk[actDate];
        resultTmp[av].docs.push(c);
    }
    else {
        d = new Object();
        d.date = actDate;
        d.docs = new Array();
        d.docs.push(c);
        resultTmp[i] = d;
        tlk[actDate] = i;
        i++;
    }
  }
});

i = 0;
var dates = [];
for(key in tlk){
    if(key )
        d = new Date(key);
    if(isValidDate(d)){
    dates[i] = new Date(key);
    i++;        
    }
}
dates.sort(function (a, b) {
    return a > b;
});

var ii = 0;
i = 0;
var ddocs;
var result = new Array();
for(i=0; i maxDocsPerDate){
            maxDocsPerDate = d.docs.length;
        } 
        result[i] = d;
}


edit3 код выше работает сейчас:

В двух словах: я использую массив tlk для отображения даты в индексе. Для одного индекса в массиве resultTmp я храню дату и набор объектов, связанных с этой датой. Следующая часть кода, которую я использую, чтобы отсортировать даты от самых старых до самых новых и аналогично отсортировать resultTemp. Сортированная версия resultTemp находится в массиве результатов.

Я представляю данные в протоколе следующим образом:


vis.add(pv.Line)
    .data(result)
    .lineWidth(2)
    .left(function(a) x(a.date))
    .bottom(function(a) y(a.docs.length))
    .add(pv.Dot)
    .lineWidth(function(a) a.docs.length - (a.docs.length-1)/3)
    .radius(function(a) a.docs.length * (a.docs.length/1.2))
    .fillStyle(function(a) color(a.docs.length))
    .event("click", function(a) Popup.show(a.docs))
    .anchor("top").add(pv.Label)
    .text(function(a) a.docs.length)
    .textBaseline("bottom");

vis.render();

Примерный результат выглядит так: i.imgur.com / WODYA.png
Я не включил код для печати осей X и Y, а также для масштабирования от даты до ширины графика. Вы можете найти примеры на странице примеров protovis.

КСТАТИ: Я запутался, почему в части:

for(key in tlk){
    dates[i] = new Date(key);
    i++;
}

Как последний ключ, который я получаю, "содержит"? Пытался найти ответ в интернете, но безуспешно. Медведс объяснил в своем комментарии, что причина, по которой я получаю эту проблему, заключается в том, что я перебираю свойства массива.

Ответы [ 3 ]

2 голосов
/ 23 августа 2010

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

for (var c in ct) {
    if (ct.hasOwnProperty(c)) {
        // do something
    }
}

Смотри также:

1 голос
/ 23 августа 2010

Метод Array.prototype.forEach обходит массив по его числовым индексам.

Массивы не являются "ассоциативными", если вы хотите иметь именованные свойства со значениями, вы должны использовать простой объект и использовать for-in оператор для перечисления существующих свойств:

var ct = {};
ct["me"]= {"name" : "Jakub"};
ct["you"]= {"name" : "stack"};

for (var prop in ct) {
  if (ct.hasOwnProperty(prop)) {
    alert(ct[prop]);
  }
}

Метод hasOwnProperty вызван, потому что оператор for-in пересекает свойства, которые унаследованы, при этом он будет перечислять только те свойства, которые физически существуют наобъект (собственные свойства).

Вы можете использовать if (Object.prototype.hasOwnProperty.call(ct, prop)) вместо if (ct.hasOwnProperty(prop)) для дополнительной безопасности, потому что, если объект имеет свойство с именем "hasOwnProperty", он не будет методом, который вы хотите выполнить.

1 голос
/ 23 августа 2010

Массивы JavaScript поддерживают индексацию только по номеру.Когда вы пишете

ct["me"]= {"name" : "Jakub"};
ct["you"]= {"name" : "stack"};

, вы добавляете специальные свойства me и you в массив;вы не добавляете элементы в массив.(Также использование конструктора new Array() довольно странно. Если вам нужен массив, используйте литерал [].)

Похоже, вы должны использовать объект JavaScript, а не массив, но будьте внимательнычто они поддерживают только строковые индексы.

var ct = {};
ct['me'] = {name: 'Jakub'};
ct['you'] = {name: 'stack'};

for (var k in ct) {
    document.getElementById('tmp', appendChild(document.createTextNode(ct[k]));
}

Редактировать: Если вы хотите обрабатывать горизонтальную ось как время, вам действительно не нужно делать намного больше работы.Вот хороший базовый пример здесь ;просмотреть исходный код страницы, чтобы увидеть код.Хитрость заключается в том, что, хотя данные действительно являются массивом (объектов), x-координата явно указывается как свойство, а не как индекс в массиве данных.Каждый элемент в массиве выглядит примерно так:

>>> data[0]
    {x: /* some JavaScript date object */, y: /* some number */ }

Источники:


Редактировать 2: Вы все еще путаетесь с массивами против объектов.

Относительно вашего "BTW": когда вы пишете for(key in tlk) ...вы перебираете ключи, которые уже есть в массиве.Это рассматривает массив как объект, и это не то, что вы хотите!Вы видите contains, потому что вы перебираете свойства массива, а contains - это функция, прикрепленная к каждому массиву (вы используете прототип или другую подобную библиотеку?).

Основная проблема,однако, это то, что вы индексируете в массив (tlk), используя Date.Это большое нет-нет;даже если tlk является объектом, потому что вы можете индексировать объекты только с использованием строк .Я действительно не понимаю, что вы делаете с tlk, но я не думаю, что вам это нужно вообще.Какова форма ваших входных данных?Если вы можете дать мне небольшой пример ввода, я, вероятно, покажу вам, что с ним делать.

Кроме того, вам действительно следует использовать литералы массивов и объектов, а не конструкторы Array и Object.,Например, используйте var tlk = [] вместо var tlk = new Array(); и var d = {}; вместо var d = new Object();.

...