web-dev-qa-db-fra.com

Tableaux associatifs multidimensionnels en JavaScript

Les résultats de la requête sont les suivants: (key1 et key2 peuvent être n’importe quel texte)

id   key1     key2     value

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

et je souhaite stocker les données dans une grille (peut-être sous forme de tableau) en boucle tous les enregistrements comme ceci:

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

Avec PHP, ce serait vraiment facile, en utilisant des tableaux associatifs:

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

Mais en JavaScript, les tableaux associatifs comme celui-ci ne fonctionnent pas .. Après avoir lu des tonnes de tutoriels, tout ce que j'ai pu obtenir, c'est

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

mais arr['fred']['Apple'] = 2; ne fonctionne pas . J'ai essayé des tableaux d'objets, mais les propriétés des objets ne peuvent pas être du texte libre .

Toute idée est la bienvenue :)

70
Omiod

Utilisez simplement un objet JavaScript classique, qui se «lirait» de la même manière que vos tableaux associatifs. N'oubliez pas de les initialiser également.

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

Si vous examinez les valeurs, vous pourriez avoir quelque chose qui ressemble à ceci:

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

Si n'a pas pour être un tableau, vous pouvez créer un objet JS "multidimensionnel" ...

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

Javascript est flexible:

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

Comme j’avais besoin d’obtenir tous les éléments d’une manière agréable, j’ai rencontré ce sujet SO "Parcourir un tableau/objet associatif à 2 dimensions" - quel que soit le nom pour moi, car la fonctionnalité compte.

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

Il semble que pour certaines applications, il existe une approche beaucoup plus simple des tableaux associatifs multidimensionnels en javascript.

  1. Etant donné que la représentation interne de tous les tableaux sont en réalité des objets d'objets, il a été démontré que le temps d'accès pour les éléments indexés numériquement est en fait le même que pour les éléments indexés associatifs (texte). 

  2. le temps d'accès pour les éléments indexés associatifs de premier niveau n'augmente pas avec le nombre d'éléments réels.

Compte tenu de cela, il peut y avoir de nombreux cas où il est préférable d'utiliser une approche de chaîne concaténée pour créer l'équivalence d'éléments multidimensionnels. Par exemple:

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

va à:

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

Les avantages comprennent:

  • pas besoin d'initialiser des sous-objets ou de trouver la meilleure combinaison des objets 
  • temps d'accès à un niveau. les objets dans les objets ont besoin de N fois le temps d'accès
  • peut utiliser Object.keys () pour extraire toutes les informations de dimension et ..
  • pouvez utiliser la fonction regex.test (chaîne) et la fonction array.map sur les touches pour extraire exactement ce que vous voulez.
  • pas de hiérarchie dans les dimensions.
  • le "point" est arbitraire - l'utilisation du trait de soulignement facilite la regex
  • il y a beaucoup de scripts pour "aplatir" JSON dans et hors de ce format aussi
  • peut utiliser toutes les autres fonctions de traitement des tableaux de Nice sur la liste de clés 
3
sdw

N'utilisez pas de tableau, utilisez un objet.

var foo = new Object();
3
Tim

Obtenez la valeur d'un tableau de propriétés de tableaux associatifs lorsque le nom de la propriété est un entier:

Commençant par un tableau associatif où les noms de propriété sont des entiers:

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

Poussez les éléments dans le tableau:

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

Boucle à travers tableau et faire quelque chose avec la valeur de la propriété.

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

La sortie de la console devrait ressembler à ceci:

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

Comme vous pouvez le constater, vous pouvez contourner la limitation de tableau associatif et attribuer un nom de propriété à un entier.

Remarque: le tableau associatif dans mon exemple est le json que vous auriez si vous sérialisé un objet Dictionary [].

3
Jason Williams

Vous n'avez pas nécessairement besoin d'utiliser des objets, vous pouvez le faire avec des tableaux multidimensionnels normaux.

Ceci est ma solution sans objets :

// Javascript
const matrix = [];

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

matrix.key2 = [
  'value3',
];

qui dans PHP est équivalent à:

// PHP
$matrix = [
    "key1" => [
        'value1',
        'value2',
    ],
    "key2" => [
        'value3',
    ]
];
1
Francesco Borzi
    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']);
      }
    }

Sortie:

  • Base trouvée
  • Base.panel.panel_base trouvé
  • ancienne valeur: Base
  • nouvelle valeur: nouvelle valeur

L'opération de tableau fonctionne. Il n'y a pas de problème.

Itération:

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

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