如何从javascript树数组中选择一个项目?

时间:2011-09-08 20:40:21

标签: javascript

我有一个javascript数组,它定义了这样的无限树。

z=['~GROUPHEAD 0~',
    'Intro',
    'Summary',
    ['~GROUPHEAD 1~',
        'Do this',
        ['~GROUPHEAD 2~',
            'Task 1',
            'Task 2'
        ]
    ]
]

现在
z[0]='~GROUPHEAD 0~';
z[1]='Intro';
z[2]='Summary';
z[3][0]='~GROUPHEAD 1~';
z[3][1]='Do this';
z[3][2][0]='~GROUPHEAD 2~';
z[3][2][1]='Task 1';
z[3][2][2]='Task 2';
z...[0] is a Header

问题

我想发送一个数字322 or 3.2.2 or [3][2][2]来选择“任务2”(即z[3][2][2]
谁能帮忙;还有更好的方法吗?

修改

我需要称之为100次

6 个答案:

答案 0 :(得分:3)

以下是一种方式:http://jsbin.com/uvenus(点击右上方的 jsbin.com 中的编辑进行播放)。这是代码:

Array.prototype.pick = function(num) {
  var levels = num.split('.');
  var out = this;
  for (var i=0;i<levels.length;i++) {
    out = out[parseInt(levels[i])];
  }
  return out;
};

// usage
myArray.pick('3.2.2');

因此,我们在名为pick的Array实例上创建一个新方法,该方法接受一个字符串(3.2.2对JS不是一个字符串以外的任何意义)。我们将它分成点,然后遍历生成的数字数组,将每个数字作为索引应用于原始数组(并且首先将索引转换为带parseInt()的整数,尽管JS会自动为您进行类型转换如果你把它遗漏了。)

如果你想让它变得更加万无一失,它应该有一些错误检查,你传入的字符串只包含有效的索引和类似的东西,但这应该让你开始! :)

答案 1 :(得分:2)

您可以拆分数字并递归查找:

var path = '3.2.2',
    root = z;

var item = (function walk( root, path ){
    root = root[ path.shift() ];
    return path.length ? walk( root, path ) : root;
})( root, path.split('.') );

或者您可以执行以下操作:

var path = '3.2.2'
  , item = eval('z[' + path.replace(/[^\d\.]/g, '').split('.').join('][') + ']');

以上一行:

  • 通过删除非数字/小数
  • 来清理字符串
  • 构造一个字符串“z [3] [2] [2]”
  • 评估此新字符串以直接为您提供结果。

如果有人通过无效路径,您应该将其包装在try/catch中。

答案 2 :(得分:2)

不使用不检查无效路径的eval的解决方案:

var z = ['~GROUPHEAD 0~',
    'Intro',
    'Summary',
    ['~GROUPHEAD 1~',
        'Do this',
        ['~GROUPHEAD 2~',
            'Task 1',
            'Task 2'
        ]
    ]
];

function accessArray(arr, index) {
    var parts = index.split(".");

    var a = arr;
    for(var i = 0; i < parts.length; i++)
        a = a[parts[i]];

    return a;
}

alert(accessArray(z, "3.2.2"));

http://jsfiddle.net/Xeon06/aHkW2/

答案 3 :(得分:1)

function selectFromArray(ar, index)
{
  //get array from indexes
  var index_ar = index.split('.');
   if(index_ar.length > 1)
    {
     //set new index value
     var indx = "";
        //append new index value
        for(var i = 1; i < index_ar.length; i++)
        {              
          if(indx.length > 0)
             indx += '.';
           indx += index_ar[i];
         }
         //call method again with new index 
         return selectFromArray(ar[intParse(index_ar[0])], indx);
     }
    //return value
    return ar[intParse(index_ar[0])];  
}

我希望我的评论能够描述这种方法的功能,但它可以解决这个问题

所以你可以像

一样调用它
selectFromArray(your_array, '3.4.3.2.1.2.3.2.2');

如果索引越界,它将失败:)

答案 4 :(得分:1)

这是一种以面向对象的方式做同样的事情。

MyCompanyGroup = function(name, description, task, parent, child) {
        if (arguments.length == 0) return;

        this._name = name;
        this._description = description;
        this._parent = parent;
        this._child = child;
}

MyCompanyGroup.prototype.toString =

function() {
        return "MyCompanyGroup";
}

var z = new MYCompanyGroup("~GROUPHEAD0~", "Intro", "Summary", this, this);

现在,您可以使用父子关系向上和向下导航层次结构 您还可以将所有这些对象存储在数组中或hashmap中以便直接访问。

如果您有不确定数量的字段,您始终可以在MyCompanyGroup中嵌入一个名称 - 值对数组

这种面向对象方法有两个主要优点

  1. 您可以在不破坏代码的情况下向此结构添加更多字段,因为数组下标不是硬编码的。
  2. 您可以按名称访问字段,以便更容易理解和维护代码。

答案 5 :(得分:0)

非常不切实际但非常有趣:P

var num = 322;

if (num < 10)
  meh = z[num];
else if (num < 100)
  meh = z[Math.floor(num/10)][Math.floor(num % 10)];
else
  meh = z[Math.floor(num/100)][Math.floor(num/10 % 10)][Math.floor(num % 10)];

meh // results in "Task 2"