JavaScript中的多维关联数组


84

有以下查询结果:(key1和key2可以是任何文本)

id   key1     key2     value

1    fred     apple    2
2    mary     orange   10
3    fred     banana   7
4    fred     orange   4
5    sarah    melon    5
...

我希望将数据存储在网格(可能是数组)中,像这样循环所有记录:

         apple    orange   banana  melon
fred        2        4         7     -
mary        -        10        -     -
sarah       -        -         -     5

在PHP中,使用关联数组非常容易:

$result['fred']['apple'] = 2;

但是在JavaScript这样的关联数组中不起作用。阅读大量教程之后,我所能得到的就是:

arr=[];
arr[1]['apple'] = 2;

arr['fred']['apple'] = 2;不起作用。我尝试了对象数组,但对象属性不能为自由文本。我读的教程越多,我就越困惑。

任何想法都欢迎:)


感谢您的答复,但我正在遍历查询结果,并且希望一次设置一个值。示例行(取自Matt示例)var grid = {};grid['aa']['bb'] = 1;返回“ Uncaught TypeError:无法设置未定义的属性'bb'”。我可能是错的,但是在大多数示例中,我必须在初始化时知道​​数据。
Omiod 2010年

刚刚发现var grid = {}; grid['aa'] = {}; grid['aa']['bb'] = 1;有效。一个更复杂的测试失败了,但看起来我走对了
Omiod 2010年

2
正如我在回答中提到的,您必须首先初始化子对象。var grid = {}; grd ['aa'] = {}; 那么您可以执行grid ['aa'] ['bb'] =1。有很多方法可以检查子对象是否已经初始化(如我的回答所述),因此您不会覆盖现有对象目的。
马特2010年

用一些其他代码更新了我的答案。不确定对象的深度或获取数据的方式,但希望会为您指明正确的方向
Matt

Answers:


152

只需使用常规JavaScript对象,该对象将“读取”与关联数组相同的方式。您还必须记住首先对其进行初始化。

var obj = {};

obj['fred'] = {};
if('fred' in obj ){ } // can check for the presence of 'fred'
if(obj.fred) { } // also checks for presence of 'fred'
if(obj['fred']) { } // also checks for presence of 'fred'

// The following statements would all work
obj['fred']['apples'] = 1;
obj.fred.apples = 1;
obj['fred'].apples = 1;

// or build or initialize the structure outright
var obj = { fred: { apples: 1, oranges: 2 }, alice: { lemons: 1 } };

如果要查看值,则可能会出现以下内容:

var people = ['fred', 'alice'];
var fruit = ['apples', 'lemons'];

var grid = {};
for(var i = 0; i < people.length; i++){
    var name = people[i];
    if(name in grid == false){
        grid[name] = {}; // must initialize the sub-object, otherwise will get 'undefined' errors
    }

    for(var j = 0; j < fruit.length; j++){
        var fruitName = fruit[j];
        grid[name][fruitName] = 0;
    }
}

设法在生产代码(Chrome扩展程序)上使用该示例,并且工作正常。谢谢。最后,我了解了如何在JS中处理对象!
Omiod

3
无法足够回答这个答案!导致我的对象不断返回undefined的部分是我没有初始化子对象。 因此,请务必执行此操作! 例如: grid[name] = {};
Jason Pudzianowski 2012年

1
@Matt是否可以仅使用一组[]获得obj.fred.apples?我假设不是。obj["fred.apples"]例如
theB3RV

如果我们不知道数组的数量,例如您的代码[javasript] var people = ['fred','alice']怎么办?var fruit = ['apples','lemons']; var color = ['red','blue'] var
.....-

我可以通过数字索引访问obj(fred)中的第一项吗?就像obj [0]会导致apples:1,oranges:2一样。我可以访问最后一个项目(爱丽丝并导致柠檬:1)吗?
蒂莫,

26

如果它不具有为一个数组,你可以创建一个“多维” JS对象...

<script type="text/javascript">
var myObj = { 
    fred: { apples: 2, oranges: 4, bananas: 7, melons: 0 }, 
    mary: { apples: 0, oranges: 10, bananas: 0, melons: 0 }, 
    sarah: { apples: 0, oranges: 0, bananas: 0, melons: 5 } 
}

document.write( myObject[ 'fred' ][ 'apples' ] );
</script>

JSON实际上是JavaScript对象的“字符串化”格式。您所拥有的不是JSON,而是一个JavaScript对象。
马特2010年

谢谢,马特。更新了帖子。
charliegriefer 2010年

1
@ charliegriefer,document.write行不应为:“ document.write(myObj ......”
约翰

13

Javascript是灵活的:

var arr = {
  "fred": {"apple": 2, "orange": 4},
  "mary": {}
  //etc, etc
};

alert(arr.fred.orange);
alert(arr["fred"]["orange"]);
for (key in arr.fred)
    alert(key + ": " + arr.fred[key]);

8
我会说变量名“ arr”在这里是一个误称,因为它实际上不是数组,而是对象。
马特2010年

我是一只懒狗,因此无法使用您的解决方案。如果我渴望的话,可以通过您的子数组示例找到自己的方式;)无论如何,感谢您的努力。
Timo

9

当我需要以一种很好的方式获取所有元素时,我遇到了这个主题“遍历二维关联数组/对象”-不管我叫什么名字,因为功能很重要。

var imgs_pl = { 
    'offer':        { 'img': 'wer-handwritter_03.png', 'left': 1, 'top': 2 },
    'portfolio':    { 'img': 'wer-handwritter_10.png', 'left': 1, 'top': 2 },
    'special':      { 'img': 'wer-handwritter_15.png', 'left': 1, 'top': 2 }
};
for (key in imgs_pl) { 
    console.log(key);
    for (subkey in imgs_pl[key]) { 
        console.log(imgs_pl[key][subkey]);
    }
}

应该接受答案,因为通常是循环。
Timo

5

似乎对于某些应用程序,JavaScript中有一种更简单的多维关联数组方法。

  1. 假定所有数组的内部表示实际上都是对象的对象,则表明数字索引元素的访问时间实际上与关联(文本)索引元素的访问时间相同。

  2. 随着实际元素数量的增加,第一级关联索引元素的访问时间不会增加。

鉴于此,在许多情况下,实际上最好使用级联字符串方法来创建多维元素的等效项。例如:

store['fruit']['apples']['granny']['price] = 10
store['cereal']['natural']['oats']['quack'] = 20

前往:

store['fruit.apples.granny.price'] = 10
store['cereal.natural.oats.quack'] = 20

优势包括:

  • 无需初始化子对象或弄清楚如何最好地组合对象
  • 单级访问时间。对象中的对象需要访问时间的N倍
  • 可以使用Object.keys()提取所有尺寸信息并..
  • 可以在按键上使用regex.test(string)函数和array.map函数来准确提取所需内容。
  • 维度中没有层次。
  • “点”是任意的-使用下划线实际上使正则表达式更容易
  • 也有很多脚本可以将JSON“展平”为这种格式
  • 可以使用键列表上的所有其他漂亮的数组处理功能

3

当属性名称是整数时,获取关联数组的属性数组的值:

从属性名称为整数的关联数组开始:

var categories = [
    {"1":"Category 1"},
    {"2":"Category 2"},
    {"3":"Category 3"},
    {"4":"Category 4"}
];

将项目推送到数组:

categories.push({"2300": "Category 2300"});
categories.push({"2301": "Category 2301"});

遍历数组并使用属性值执行某些操作。

for (var i = 0; i < categories.length; i++) {
    for (var categoryid in categories[i]) {
        var category = categories[i][categoryid];
        // log progress to the console
        console.log(categoryid + " : " + category);
        //  ... do something
    }
}

控制台输出应如下所示:

1 : Category 1
2 : Category 2
3 : Category 3
4 : Category 4
2300 : Category 2300
2301 : Category 2301

如您所见,您可以绕开关联数组限制,并将属性名称设置为整数。

注意:在我的示例中,关联数组是序列化Dictionary []对象时将拥有的json。


3

不要使用数组,而要使用对象。

var foo = new Object();

2
不要使用new Object(),因为Object.prototype可能会附有怪异字样;使用对象字面量:var foo = {};
Michael Paulukonis

1
@Michael我认为{}只是新Object()的语法糖;很像[]是新Array()的简称
Matt

1
在我的Chrome JS控制台中,这两个构造看起来都是相同的,包括它们的原型。甚至都添加了Object.prototype.foo = function(){}。
马特2010年

1
@Matt我想我错了new Array(),应该避免使用。啊。
Michael Paulukonis

1
@Michael为什么应避免使用new Array()?
马特2010年

2

您不必一定要使用对象,可以使用普通的多维数组来实现。

这是我没有对象的解决方案:

// Javascript
const matrix = [];

matrix.key1 = [
  'value1',
  'value2',
];

matrix.key2 = [
  'value3',
];

PHP中的等效于:

// PHP
$matrix = [
    "key1" => [
        'value1',
        'value2',
    ],
    "key2" => [
        'value3',
    ]
];

1
以后如何循环(使用每个循环)?
Sagive SEO '18年

0

<script language="javascript">

// Set values to variable
var sectionName = "TestSection";
var fileMap = "fileMapData";
var fileId = "foobar";
var fileValue= "foobar.png";
var fileId2 = "barfoo";
var fileValue2= "barfoo.jpg";

// Create top-level image object
var images = {};

// Create second-level object in images object with
// the name of sectionName value
images[sectionName] = {};

// Create a third level object
var fileMapObj = {};

// Add the third level object to the second level object
images[sectionName][fileMap] = fileMapObj;

// Add forth level associate array key and value data
images[sectionName][fileMap][fileId] = fileValue;
images[sectionName][fileMap][fileId2] = fileValue2;


// All variables
alert ("Example 1 Value: " + images[sectionName][fileMap][fileId]);

// All keys with dots
alert ("Example 2 Value: " + images.TestSection.fileMapData.foobar);

// Mixed with a different final key
alert ("Example 3 Value: " + images[sectionName]['fileMapData'][fileId2]);

// Mixed brackets and dots...
alert ("Example 4 Value: " + images[sectionName]['fileMapData'].barfoo);

// This will FAIL! variable names must be in brackets!
alert ("Example 5 Value: " + images[sectionName]['fileMapData'].fileId2);
// Produces: "Example 5 Value: undefined".

// This will NOT work either. Values must be quoted in brackets.
alert ("Example 6 Value: " + images[sectionName][fileMapData].barfoo);
// Throws and exception and stops execution with error: fileMapData is not defined

// We never get here because of the uncaught exception above...
alert ("The End!");
</script>


0
    var myObj = [];
    myObj['Base'] = [];
    myObj['Base']['Base.panel.panel_base'] = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',  AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };
    myObj['Base']['Base.panel.panel_top']  = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };

    myObj['SC1'] = [];
    myObj['SC1']['Base.panel.panel_base'] = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',  AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };
    myObj['SC1']['Base.panel.panel_top']  = {ContextParent:'',ClassParent:'',NameParent:'',Context:'Base',Class:'panel',Name:'panel_base',Visible:'',ValueIst:'',ValueSoll:'',
                                              Align:'',AlignFrom:'',AlignTo:'',Content:'',onClick:'',Style:'',content_ger_sie:'',content_ger_du:'',content_eng:'' };


    console.log(myObj);

    if ('Base' in myObj) {
      console.log('Base found');

      if ('Base.panel.panel_base' in myObj['Base'])  {
        console.log('Base.panel.panel_base found'); 


      console.log('old value: ' + myObj['Base']['Base.panel.panel_base'].Context);  
      myObj['Base']['Base.panel.panel_base'] = 'new Value';
      console.log('new value: ' + myObj['Base']['Base.panel.panel_base']);
      }
    }

输出:

  • 找到基地
  • 找到Base.panel.panel_base
  • 旧值:基础
  • 新价值:新价值

阵列操作有效。没有问题。

迭代:

     Object.keys(myObj['Base']).forEach(function(key, index) {            
        var value = objcons['Base'][key];                   
      }, myObj);

2
欢迎使用stackoverflow。请编辑您的答案,并解释为什么您的代码段可以解决问题。更多信息在这里:如何回答
Djensen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.