Получение JavaScript для поиска в массиве в массиве - PullRequest
1 голос
/ 28 ноября 2009

У меня есть следующий javascript для обхода массива записей и предупреждения о количестве совпадений, найденных в массиве, для каждого поля:

    mymusic=[{title:"a",artist:"b",artwork:"c",tracks:[{tracktitle:"d",trackmp3:"e"}]}];
tracksArray=[];
trackTitles=[];
var albumScore=0;
var artistScore=0;
var tracksScore=0;
stringToSearchFor="d";
for(i=0;i<mymusic.length;i++){
    if((mymusic[i].title).match(stringToSearchFor))
        albumScore+=1;
    }
if(albumScore!=0)
    alert(albumScore+" match(es) found in Albums");
else
    alert("No matches found in Albums");
for(d=0;d<mymusic.length;d++){
    if((mymusic[d].artist).match(stringToSearchFor))
        artistScore+=1;
    }
if(artistScore!=0)
    alert(artistScore+" match(es) found in Artists");
else
    alert("No matches found in Artists");
for(f=0;f<mymusic.length;f++){
    tracksArray[f]=mymusic[f].tracks;
    for(g=0;g<tracksArray;g++){
        trackTitles[g]=tracksArray[g].tracktitle;
        }
    for(h=0;h<trackTitles.length;h++){
        if(trackTitles(h).match(stringToSearchFor))
            {
            tracksScore+=1;
            }
        }
    }
if(tracksScore!=0)
    alert(tracksScore+" match(es) found in Tracks");
else
    alert("No matches found in Tracks");

, который отлично работает для записей "title" и "Artist", но всегда выдает предупреждение "Не найдено совпадений" для записи "дорожек", даже если есть совпадения. Я предполагаю, что проблема заключается во вложенном цикле for в массиве trackTitles, но я не вижу, что можно изменить, чтобы заставить его работать. Есть идеи? Спасибо

Ответы [ 5 ]

2 голосов
/ 28 ноября 2009
if(trackTitles(h)

Вы вызываете Массив. Должны быть квадратные скобки.

Можно было бы разбить элементы обработки массива на многократно используемые функции, чтобы улучшить читаемость и уменьшить количество этих случайных переменных.

Поскольку уже есть ответы с процедурными подходами, вот один, основанный на функционально-подобной обработке массивов для дополнительного удовольствия (*):

function countItemsContaining(seq, prop, str) {
    return seq.map(itemGetter(prop)).filter(function(s) {
        return s.indexOf(str)!==-1;
    }).length;
}

function itemGetter(prop) {
    return function(o) {
        return o[prop];
    };
}


mymusic= [{title:"a",artist:"b",artwork:"c",tracks:[{tracktitle:"d",trackmp3:"e"}]}];
needle= 'd';

var titleScore= countItemsContaining(mymusic, 'title', needle);
var artistScore= countItemsContaining(mymusic, 'artist', needle);

// Calling concat is a JavaScript idiom to combine a load of lists into one
//
var mytracks= [].concat.apply([], mymusic.map(itemGetter('tracks')));
var tracksScore= countItemsContaining(mytracks, 'tracktitle', needle);

array.map и array.filter стандартизированы в пятом издании ECMAScript, но еще не доступны в IE, поэтому для совместимости вы можете определить их следующим образом:

if (!('map' in Array.prototype)) {
    Array.prototype.map= function(f, that) {
        var a= new Array(this.length);
        for (var i= 0; i<this.length; i++) if (i in this)
            a[i]= f.call(that, this[i], i, this);
        return a;
    };
}

if (!('filter' in Array.prototype)) {
    Array.prototype.filter= function(f, that) {
        var a= [];
        for (var i= 0; i<this.length; i++) if (i in this)
            if (f.call(that, this[i], i, this))
                a.push(this[i]);
        return a;
    };
}

(*: количество фактического веселья, содержащегося в ответе, может быть ограничено)

1 голос
/ 28 ноября 2009

Взгляните на библиотеку под названием underscore.js . Это сделано для такого рода вещей. Эти задачи часто сводятся к одной или двум строчкам из простого для чтения кода.

Он использует нативные методы, когда они доступны, заполняет пропущенные биты (в зависимости от браузера) и является цепным. Это даже делает встроенные методы массивов связными.

0 голосов
/ 28 ноября 2009

Что сказали Энтони У. Джонс и Бобинс (хотя мне нужно потратить некоторое время на чтение ответа Бобинса).

Альтернативное решение: в тот момент, когда я увидел структуру данных, я подумал "рекурсия"! и подумал, что было бы интересно посмотреть, смогу ли я найти решение, которое будет работать с любой структурой данных любого размера (неизвестного) уровня глубины.

Я не часто пишу код, поэтому приведенные ниже могут быть пронизаны плохой практикой, но это работает :). Дайте мне знать ваши мысли.

myMusic=[{title:"a",artist:"b",artwork:"c",year:"d",tracks:[{tracktitle:"d",trackmp3:"e"}]}];

function find_match(dataObj,stringToSearchFor,resultObj){

  resultObj = (resultObj)?resultObj:{}; //init resultObj

  for (dataKey in dataObj){ //loop through dataObj
    if (typeof(dataObj[dataKey]) == "object"){ //if property is array/object, call find_match on property
     resultObj = find_match(dataObj[dataKey],stringToSearchFor,resultObj); 
    }else if (dataObj[dataKey].match(stringToSearchFor)){ //else see if search term matches    
      resultObj[dataKey] = (resultObj[dataKey] )?resultObj[dataKey] +=1:1; //add result to resultObj, init key if not yet found, use dataObj key as resultObj key 
    }
  }

  return resultObj; //return resultObj up the chain

}

results = find_match(myMusic,"d");

alertString = "";

for (resultKey in results){ //loop  through results and construct alert msg.
  alertString += results[resultKey] + " match(es) found in " + resultKey + "\n";
}

alert(alertString );
0 голосов
/ 28 ноября 2009

У вас есть ряд основных ошибок, которые в конечном итоге происходят из-за слишком большого количества переменных. Вот ваш код рефакторинг: -

mymusic=[{title:"a",artist:"b",artwork:"c",tracks:[{tracktitle:"d",trackmp3:"e"}]}];
var albumScore=0;
var artistScore=0;
var tracksScore=0;
stringToSearchFor="d";

for (var i=0; i < mymusic.length; i++)
{
    if( mymusic[i].title.match(stringToSearchFor))
        albumScore += 1;

    if( mymusic[i].artist.match(stringToSearchFor))
        artistScore += 1;

    for (var j = 0; j < mymusic[i].tracks.length; j++)
    {
        if (mymusic[i].tracks[j].tracktitle.match(stringToSearchFor))
            tracksScore += 1
    }
}

if (albumScore != 0)
    alert(albumScore + " match(es) found in Albums");
else
    alert("No matches found in Albums");

if (artistScore != 0)
    alert(artistScore + " match(es) found in Artists");
else
    alert("No matches found in Artists");

if (tracksScore != 0)
    alert(tracksScore+" match(es) found in Tracks");
else
    alert("No matches found in Tracks");
0 голосов
/ 28 ноября 2009

Попробуйте вместо этого:

var tracksScore=0;
stringToSearchFor="d";
for(var f=0;f<mymusic.length;f++){
    var tracksArray=mymusic[f].tracks;
    for(var g=0;g<tracksArray.length;g++) {
        var tracktitle=tracksArray[g].tracktitle;
        if(tracktitle.match(stringToSearchFor))
        {
                tracksScore+=1;
        }
    }
}
if(tracksScore!=0)
    alert(tracksScore+" match(es) found in Tracks");
else
    alert("No matches found in Tracks");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...