2010-12-01 8 views
59

Il y a les résultats de requête suivants: (key1 et key2 pourrait être tout texte)tableaux associatifs multidimensionnels en JavaScript

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 comme un tableau) boucle tous les dossiers comme celui-ci:

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

En 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 tutoriel, tout ce que je pouvais faire était le suivant:

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. Plus je lisais des tutoriels, plus je suis confus ...

Toute idée est la bienvenue :)

+0

Merci pour les réponses, mais je suis en boucle à travers les résultats de la requête, et je souhaite définir les valeurs une à la fois. Les lignes d'exemple (extrait de l'exemple Matt) 'var grille = {}; grille ['aa'] ['bb'] = 1;' renvoie "Uncaught TypeError: Impossible de définir la propriété 'bb' de undefined". Je peux me tromper, mais avec la plupart de vos exemples, je dois connaître les données au moment de l'initialisation. – Omiod

+0

Je viens de trouver que 'var grid = {}; grille ['aa'] = {}; grid ['aa'] ['bb'] = 1; 'fonctionne. Un test plus complexe échoue, mais on dirait que je suis dans le bon chemin – Omiod

+1

vous devez d'abord initialiser le sous-objet, comme je l'ai mentionné dans ma réponse. var grille = {}; grd ['aa'] = {}; * then * vous pouvez faire grid ['aa'] ['bb'] = 1. Il y a plusieurs façons de vérifier si le sous-objet est déjà initialisé (comme mentionné dans ma réponse), donc vous ne devez pas écraser un objet existant. – Matt

Répondre

121

Utilisez simplement un objet JavaScript normal, qui "lira" de la même manière que vos tableaux associatifs. Vous devez vous rappeler de les initialiser d'abord aussi bien.

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 êtes à la recherche sur 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; 
    } 
} 
+0

Géré pour utiliser l'exemple sur le code de production (une extension Chrome), et fonctionne très bien. Je n'arrive pas à gérer cette objet dans JS! – Omiod

+3

La partie qui faisait que mon objet revenait continuellement indéfini était que je n'étais PAS en train d'initialiser le sous-objet. ! ** _example: _ 'grid [nom] = {};' –

+0

@iSofia vous êtes les bienvenus – Matt

3

Ne pas utiliser un tableau, utilisez un objet.

 var foo = new Object(); 
+1

ne pas utiliser un 'new Object()', car le Object.prototype pourrait avoir de l'étrangeté attaché ; utilisez l'objet littéral: 'var foo = {};' –

+0

@Michael Je pensais que {} n'était que du sucre syntaxique pour new Object(); Tout comme [] est l'abréviation de nouveau Array() – Matt

+0

de ma console Chrome JS, ces deux constrcuts semblent identiques, y compris leurs prototypes. Même ajouter Object.prototype.foo = function() {} apparaît dans les deux. – Matt

9

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

Je dirais que le nom de variable 'arr' est un terme inapproprié ici, parce que ce n'est pas vraiment un tableau, mais un objet. – Matt

21

Si cela n'a pas ont être un tableau, vous pouvez créer un "multidimensionnel" objet 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> 
+0

JSON est en fait le format «stringifié» de l'objet JavaScript. Ce que vous avez là n'est pas JSON, juste un objet JavaScript. – Matt

+0

Merci, Matt. Mise à jour du post. – charliegriefer

+0

@charliegriefer, la ligne document.write ne devrait pas être: "document.write (myObj ......" – john

6

que je avais besoin obtenir tous les éléments d'une manière agréable, je rencontrais ce sujet SO. traversant 2 tableau associatif dimensions/objet - peu importe 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]); 
     }//for 

    }//for 
3

Obtenir la valeur pour un tableau de la propriété de tableaux associatifs lorsque le nom de la propriété est un entier:

A partir de un tableau où les associatif noms de propriété sont des entiers:

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

Pousser les articles au tableau:

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

Parcourez la matrice et effectuez une opération 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 
    } 
} 

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 voir, vous pouvez contourner la limitation du tableau associatif et un nom de propriété soit un entier. REMARQUE: Le tableau associatif dans mon exemple est le json que vous auriez si vous sérialisiez un objet Dictionary [].

2

Il semble que pour certaines applications, il existe une approche beaucoup plus simple pour les tableaux associatifs multidimensionnels en javascript. 1) Etant donné que la représentation interne de tous les tableaux est en réalité un objet, il a été montré que le temps d'accès aux éléments indexés numériquement est le même que pour les éléments indexés (texte) associatifs. 2) le temps d'accès pour les éléments indexés associatifs de premier niveau n'augmente pas au fur et à mesure que le nombre d'éléments réels augmente. 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'un élément multidimensionnel. 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 incluent:

  • pas besoin d'initialiser des sous-objets ou comprendre comment mieux combiner les objets
  • un seul niveau temps d'accès. objets dans les objets besoin N fois le temps d'accès
  • peut utiliser Object.keys() pour extraire toutes les informations de dimension et ..
  • peut utiliser la fonction regex.test (chaîne) et la fonction array.map sur les touches pour sortez exactement ce que vous voulez.
  • aucune hiérarchie dans les dimensions.
  • le « point » est arbitraire - en utilisant soulignement rend effectivement regex plus facile
  • il y a beaucoup de scripts pour « aplatir » JSON dans et hors de ce format ainsi
  • peut utiliser toutes les autres fonctions de traitement du tableau agréable sur keylist
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

vous ne devez nécessairement utiliser des objets, vous pouvez le faire avec multi-dimension normale al Arrays.

C'est ma solution sans objets:

// Javascript 
const matrix = []; 

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

matrix.key2 = [ 
    'value3', 
]; 

qui en PHP équivaut à:

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