2009-11-28 4 views
1

У меня есть следующий JavaScript Переберите массив записей, и оповещать количество найденных в пределах массива, для каждого поля:Получения 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-loop через массив trackTitles, но я не вижу, что я могу изменить, чтобы заставить его работать. Есть идеи? Благодаря

+0

Разделить это на методы в следующий раз. Этот код выглядит нечитаемым :( –

ответ

0

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

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"); 
+0

Должно быть 'var f' и' var g' –

+0

Исправлено, спасибо. Это была ошибка в исходном коде. Я попытался исправить код, не внес слишком много изменений, но я думаю, исправлена ​​и эта ошибка. –

0

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

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"); 
2
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

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

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

0

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

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

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

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);