【问题标题】:Getting javascript to search an array within an array让javascript在数组中搜索数组
【发布时间】:2009-11-28 18:36:18
【问题描述】:

我有以下 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");

这适用于“标题”和“艺术家”记录,但对于“曲目”记录,即使存在匹配项,也会始终提示“未找到匹配项”。我想问题在于通过 trackTitles 数组的嵌套 for 循环,但我看不出我可以改变什么来使它工作。有任何想法吗? 谢谢

【问题讨论】:

  • 下次将其拆分为方法。这段代码看起来不可读:(

标签: javascript arrays search


【解决方案1】:
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.maparray.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;
    };
}

(*:答案中包含的实际乐趣可能有限)

【讨论】:

    【解决方案2】:

    看看名为underscore.js 的库。它是为这种东西而生的。这些任务通常归结为一两行易于阅读的代码。

    它在可用时使用本机方法,填充缺失的位(取决于浏览器)并且是可链接的。它甚至使内置的数组方法可链接。

    【讨论】:

      【解决方案3】:

      试试这个:

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

      【讨论】:

      • 应该是var fvar g
      • 已修复,谢谢。这是原始代码中的错误。我试图在不进行太多更改的情况下修复代码,但我想我也可以修复该错误。
      【解决方案4】:

      您有许多基本错误,这些错误最终源于变量过多。这是重构的代码:-

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

      【讨论】:

        【解决方案5】:

        AnthonyWJones 和 bobince 所说的话(尽管我需要花一些时间阅读 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 );
        

        【讨论】:

          猜你喜欢
          • 2017-03-26
          • 2011-09-12
          • 2015-07-02
          • 2016-11-08
          • 2020-02-01
          • 2012-12-19
          • 1970-01-01
          • 2011-04-07
          相关资源
          最近更新 更多