JavaScript 中的多维关联数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4329092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 11:56:09  来源:igfitidea点击:

Multi-dimensional associative arrays in JavaScript

javascriptmultidimensional-arrayassociative-array

提问by Omiod

There is the following query results: (key1 and key2 could be any text)

查询结果如下:(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
...

and I wish to store the data in a grid (maybe as an array) loopingall the records like this:

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

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

In PHP this would be really easy, using associative arrays:

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

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

But in JavaScript associative arrays like this doesn't work. After reading tons of tutorial, all I could get was this:

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

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

but arr['fred']['apple'] = 2;doesn't work. I tried arrays of objects, but objects properties can't be free text. The more I was reading tutorials, the more I got confused...

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

Any idea is welcome :)

欢迎任何想法:)

回答by Matt

Just use a regular JavaScript object, which would 'read' the same way as your associative arrays. You have to remember to initialize them first as well.

只需使用常规 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 } };

If you're looking over values, you might have something that looks like this:

如果您正在查看值,您可能会看到如下所示的内容:

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

回答by charliegriefer

If it doesn't haveto be an array, you can create a "multidimensional" JS object...

如果它不具有为一个数组,你可以创建一个“多维” 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>

回答by cambraca

Javascript is flexible:

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

回答by Michal - wereda-net

As I needed get all elements in a nice way I encountered this SO subject "Traversing 2 dimensional associative array/object" - no matter the name for me, because functionality counts.

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

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

回答by sdw

It appears that for some applications, there is a far simpler approach to multi dimensional associative arrays in javascript.

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

  1. Given that the internal representation of all arrays are actually as objects of objects, it has been shown that the access time for numerically indexed elements is actually the same as for associative (text) indexed elements.

  2. the access time for first-level associative indexed elements does not rise as the number of actual elements increases.

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

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

Given this, there may be many cases where it is actually better to use a concatenated string approach to create the equivalence of a multidimensional elements. For example:

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

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

goes to:

去:

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

Advantages include:

优点包括:

  • no need to initialize sub-objects or figure out how to best combine objects
  • single-level access time. objects within objects need N times the access time
  • can use Object.keys() to extract all dimension information and..
  • can use the function regex.test(string) and the array.map function on the keys to pull out exactly what you want.
  • no hierarchy in the dimensions.
  • the "dot" is arbitrary - using underscore actually makes regex easier
  • there are lots of scripts for "flattening" JSON into and out of this format as well
  • can use all of the other nice array processing functions on keylist
  • 无需初始化子对象或弄清楚如何最好地组合对象
  • 单级访问时间。对象内的对象需要 N 倍的访问时间
  • 可以使用 Object.keys() 提取所有维度信息并..
  • 可以在键上使用函数 regex.test(string) 和 array.map 函数来准确地拉出你想要的东西。
  • 维度中没有层次结构。
  • “点”是任意的 - 使用下划线实际上使正则表达式更容易
  • 也有很多脚本可以将 JSON“扁平化”到这种格式中,或者从这种格式中取出
  • 可以在 keylist 上使用所有其他不错的数组处理函数

回答by Jason Williams

Get the value for an array of associative arrays's property when the property name is an integer:

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

Starting with an Associative Array where the property names are integers:

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

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

Push items to the array:

将项目推送到数组:

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

Loop through array and do something with the property value.

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

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
    }
}

Console output should look like this:

控制台输出应如下所示:

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

As you can see, you can get around the associative array limitation and have a property name be an integer.

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

NOTE: The associative array in my example is the json you would have if you serialized a Dictionary[] object.

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

回答by Tim

Don't use an array, use an object.

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

var foo = new Object();

回答by Francesco Borzi

You don't need to necessarily use Objects, you can do it with normal multi-dimensional Arrays.

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

This is my solution without Objects:

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

// Javascript
const matrix = [];

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

matrix.key2 = [
  'value3',
];

which in PHP is equivalent to:

在 PHP 中相当于:

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

回答by Necips

    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']);
      }
    }

Output:

输出:

  • Base found
  • Base.panel.panel_base found
  • old value: Base
  • new value: new Value
  • 找到基地
  • 找到 Base.panel.panel_base
  • 旧值:基础
  • 新值:新值

The array operation works. There is no problem.

数组操作有效。没有问题。

Iteration:

迭代:

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

回答by Rich Schramm

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