Подтвердить что ты не робот

Javascript массив ассоциативный И проиндексирован?

может ли массив в JS быть ассоциативным и индексированным? Я хотел бы иметь возможность искать элемент в массиве по его позиции или значению ключа. возможно?

4b9b3361

Ответ 1

В Javascript нет таких вещей, как ассоциативные массивы. Вы можете использовать объектные литералы, которые выглядят как ассоциативные массивы, но у них есть неупорядоченные свойства. Регулярные массивы Javascript основаны на целых индексах и не могут быть ассоциативными.

Например, с помощью этого объекта:

var params = {
    foo: 1,
    bar: 0,
    other: 2
};

Вы можете получить доступ к свойствам объекта, например:

params["foo"];

И вы также можете перебирать объект с помощью инструкции for...in:

for(var v in params) {
    //v is equal to the currently iterated property
}

Тем не менее, нет строгого правила о порядке итерации свойств - две итерации вашего литерала объекта могут возвращать свойства в разных порядках.

Ответ 2

После прочтения определения ассоциативного массива Википедии я собираюсь сломать традиционные знания JavaScript и сказать: "Да, у JavaScript есть ассоциативные массивы". С помощью массивов JavaScript вы можете добавлять, переназначать, удалять и искать значения по своим ключам (и ключи могут быть кавычками), что Википедия говорит, что ассоциативные массивы должны быть в состоянии сделать.

Однако вы, кажется, задаете что-то другое - можете ли вы найти то же значение по индексу или ключу. Это не требование ассоциативных массивов (см. Статью в Википедии). Ассоциативные массивы не должны давать вам возможность получать значение по индексу.

Матрицы JavaScript очень близки к объектам JavaScript.

  arr=[];
  arr[0]="zero";
  arr[1]="one";
  arr[2]="two";
  arr["fancy"]="what?";

Да, это массив, и да, вы можете уйти с нечисловыми индексами. (Если вам интересно, после всего этого, arr.length равно 3.)

В большинстве случаев, я думаю, вы должны придерживаться числовых индексов при использовании массивов. Я думаю, что большинство программистов ожидают.

Ссылка на мое сообщение в блоге о теме.

Ответ 3

Собственные объекты JS принимают только строки как имена свойств, которые являются истинными даже для числовых индексов массива; массивы отличаются от ванильных объектов только в том случае, если большинство реализаций JS будут хранить числовые индексированные свойства по-разному (т.е. в фактическом массиве до тех пор, пока они плотны), и их установка приведет к дополнительным операциям (например, настройке свойства length).

Если вы ищете карту, которая принимает произвольные ключи, вам придется использовать неродную реализацию. script предназначен для быстрой итерации, а не для произвольного доступа по числовым индексам, поэтому он может и не быть тем, что вы ищете.

Реализация карты, которая будет делать то, что вы просите, будет иметь вид:

function Map() {
    this.length = 0;
    this.store = {};
}

Map.prototype.get = function(key) {
    return this.store.hasOwnProperty(key) ?
        this.store[key] : undefined;
};

Map.prototype.put = function(key, value, index) {
    if(arguments.length < 3) {
        if(this.store.hasOwnProperty(key)) {
            this.store[key].value = value;
            return this;
        }

        index = this.length;
    }
    else if(index >>> 0 !== index || index >= 0xffffffff)
        throw new Error('illegal index argument');

    if(index >= this.length)
        this.length = index + 1;

    this[index] = this.store[key] =
        { index : index, key : key, value : value };

    return this;
};

Аргумент index put() не является обязательным.

Вы можете получить доступ к значениям на карте map либо по клавише, либо по индексу с помощью

map.get('key').value
map[2].value

Ответ 4

Порядок, в котором объекты отображаются в ассоциативном массиве javascript, не определен и будет отличаться в разных реализациях. По этой причине вы не можете рассчитывать, что данный ассоциативный ключ всегда будет с одним и тем же индексом.

ИЗМЕНИТЬ:

как указывает Perspx, в javascript нет истинных ассоциативных массивов. Утверждение foo["bar"] является просто синтаксическим сахаром для foo.bar

Если вы доверяете браузеру для поддержания порядка элементов в объекте, вы можете написать функцию

function valueForIndex(obj, index) {

    var i = 0;
    for (var key in obj) {

        if (i++ == index)
            return obj[key];
    }
}

Ответ 5

var myArray = Array();
myArray["first"] = "Object1";
myArray["second"] = "Object2";
myArray["third"] = "Object3";

Object.keys(myArray);              // returns ["first", "second", "third"]
Object.keys(myArray).length;       // returns 3

если вы хотите использовать первый элемент, вы можете использовать его так:

myArray[Object.keys(myArray)[0]];  // returns "Object1"

Ответ 6

var stuff = [];
stuff[0] = "foo";
stuff.bar = stuff[0]; // stuff.bar can be stuff["bar"] if you prefer
var key = "bar";
alert(stuff[0] + ", " + stuff[key]); // shows "foo, foo"

Ответ 7

Хотя я согласен с полученными ответами, вы действительно можете выполнить то, что вы говорите, с помощью геттеров и сеттеров. Например:

var a = [1];
//This makes a["blah"] refer to a[0]
a.__defineGetter__("blah", function(){return this[0]});
//This makes a["blah"] = 5 actually store 5 into a[0]
a.__defineSetter__("blah", function(val){ this[0] = val});

alert(a["blah"]); // emits 1
a["blah"] = 5;
alert(a[0]); // emits 5

Это то, что вы ищете? я думаю, что это другой более современный способ делать геттеры и сеттеры, но не помню.

Ответ 8

Я пришел сюда, чтобы узнать, плохо ли это или нет, и вместо этого обнаружил, что многие люди не понимают вопроса.

Я хотел иметь структуру данных, которая была заказана, но может быть проиндексирована ключом, так что для каждого поиска не потребуется итерация.

В практические времена это довольно просто, но я до сих пор ничего не читал о том, ужасная практика или нет.

var roygbiv = [];
var colour = { key : "red", hex : "#FF0000" };
roygbiv.push(colour);
roygbiv[colour.key] = colour;
...
console.log("Hex colours of the rainbow in order:");
for (var i = 0; i < roygbiv.length; i++) {
    console.log(roygbiv[i].key + " is " + roygbiv[i].hex);
}

// input = "red";
console.log("Hex code of input colour:");
console.log(roygbiv[input].hex);

Важно, чтобы никогда не изменять значение массива [index] или array [key] непосредственно после того, как объект настроен, или значения больше не будут соответствовать. Если массив содержит объекты, вы можете изменить свойства этих объектов, и вы сможете получить доступ к измененным свойствам любым способом.

Ответ 9

Прилив изменился на этом. Теперь вы можете сделать это... и БОЛЬШЕ! Используя Harmony Proxies, вы могли бы решить эту проблему во многих отношениях.

Вам нужно будет убедиться, что ваши целевые среды поддерживают это, возможно, небольшую помощь из harmony-reflect shim.

Там действительно хороший пример в Mozilla Developer Network по использованию прокси-сервера для найти объект элемента массива по своему свойству, который в значительной степени его суммирует вверх.

Здесь моя версия:

  var players = new Proxy(
  [{
    name: 'monkey',
    score: 50
  }, {
    name: 'giraffe',
    score: 100
  }, {
    name: 'pelican',
    score: 150
  }], {
    get: function(obj, prop) {
      if (prop in obj) {
        // default behavior
        return obj[prop];
      }
      if (typeof prop == 'string') {

        if (prop == 'rank') {
          return obj.sort(function(a, b) {
            return a.score > b.score ? -1 : 1;
          });
        }

        if (prop == 'revrank') {
          return obj.sort(function(a, b) {
            return a.score < b.score ? -1 : 1;
          });
        }

        var winner;
        var score = 0;
        for (var i = 0; i < obj.length; i++) {
          var player = obj[i];
          if (player.name == prop) {
            return player;
          } else if (player.score > score) {
            score = player.score;
            winner = player;
          }
        }

        if (prop == 'winner') {
          return winner;
        }
        return;
      }

    }
  });

  console.log(players[0]); // { name: 'monkey', score: 50 }
  console.log(players['monkey']); // { name: 'monkey', score: 50 }
  console.log(players['zebra']); // undefined
  console.log(players.rank); // [ { name: 'pelican', score: 150 },{ name: 'giraffe', score: 100 }, { name: 'monkey', score: 50 } ]
  console.log(players.revrank); // [ { name: 'monkey', score: 50 },{ name: 'giraffe', score: 100 },{ name: 'pelican', score: 150 } ]
  console.log(players.winner); // { name: 'pelican', score: 150 }

Ответ 10

Да.

test = new Array();
test[0] = 'yellow';
test['banana'] = 0;
alert(test[test['banana']]);