Sử dụng một số nguyên làm khóa trong một mảng kết hợp trong JavaScript


102

Khi tôi tạo một mảng JavaScript mới và sử dụng một số nguyên làm khóa, mỗi phần tử của mảng đó tối đa là số nguyên được tạo dưới dạng không xác định.

Ví dụ:

var test = new Array();
test[2300] = 'Some string';
console.log(test);

sẽ xuất ra 2298 không xác định và một 'Chuỗi nào đó'.

Làm cách nào để JavaScript sử dụng 2300 dưới dạng một chuỗi thay vì một số nguyên hoặc làm cách nào để ngăn JavaScript khởi tạo 2299 chỉ số trống?

Câu trả lời:


128

Sử dụng một đối tượng, như mọi người đang nói. Tuy nhiên, lưu ý rằng bạn không thể có các khóa số nguyên. JavaScript sẽ chuyển đổi số nguyên thành một chuỗi . Các kết quả đầu ra sau 20, không phải là không xác định:

var test = {}
test[2300] = 20;
console.log(test["2300"]);

12
+1 Lưu ý rằng điều này thậm chí đúng với Mảng! xem stackoverflow.com/questions/1450957/…
bobince

1
@bobince: Trong nội bộ, chắc chắn. Tuy nhiên, về mặt logic , mảng có các "khóa" số nguyên.
Các cuộc đua ánh sáng trong quỹ đạo

1
Xin lưu ý rằng việc sử dụng số nguyên làm khóa sẽ thay đổi độ dài mảng của bạn. Bạn chắc chắn nên sử dụng Object thay thế. Tôi chỉ muốn sử dụng id facebook làm khóa và JSON.stringify sẽ làm hỏng máy của tôi;)
Krystian

2
@LightnessRacesinOrbit Mặc dù vậy, các chi tiết bên trong vẫn có thể lọt ra ngoài và cắn bạn. Xem phiên bản đơn giản hóa này của những gì tôi gặp phải ngày hôm nay: jsfiddle.net/cincodenada/pseujLex/2 Nó có vẻ giống với khi được giảm bớt, nhưng là một phần thú vị của một tập lệnh lớn hơn (và ít hơn một chút trong CoffeeScript: jsfiddle.net/ cincodenada / oojr7Ltn / 2 ). Chi tiết triển khai có vẻ như này khiến tôi phải tìm kiếm một chút lỗi trong ngày hôm nay.
cincodenada

1
Một lưu ý nhỏ cho các số không phải là số nguyên: 0.25.25giải quyết cho cùng một chuỗi "0.25". Vì vậy, nếu bạn đang sử dụng các phím phân đoạn, bạn có thể lấy tài sản của một phím số lượng thiết lập 0.25sử dụng 0.25, .25, "0.25"nhưng không phải ".25".
Sandy Gifford

34

Bạn chỉ có thể sử dụng một đối tượng:

var test = {}
test[2300] = 'Some string';

16
Vẫn được truyền sang chuỗi.
hòa 010

1
@ draw010 vâng, các đối tượng của Javascript chỉ cho phép lập chỉ mục bằng chuỗi.
Pithikos

22

Như mọi người vẫn nói, JavaScript sẽ chuyển đổi một chuỗi số thành số nguyên, vì vậy không thể sử dụng trực tiếp trên một mảng kết hợp, nhưng các đối tượng sẽ hoạt động với bạn theo cách tương tự như tôi nghĩ.

Bạn có thể tạo đối tượng của mình:

var object = {};

Và thêm các giá trị khi mảng hoạt động:

object[1] = value;
object[2] = value;

Điều này sẽ cung cấp cho bạn:

{
  '1': value,
  '2': value
}

Sau đó, bạn có thể truy cập nó giống như một mảng ở các ngôn ngữ khác để lấy khóa:

for(key in object)
{
   value = object[key] ;
}

Tôi đã thử nghiệm và hoạt động.


17

Nếu trường hợp sử dụng đang lưu trữ dữ liệu trong một tập hợp thì ECMAScript 6 cung cấpMap kiểu.

Nó chỉ nặng hơn để khởi tạo.

Đây là một ví dụ:

const map = new Map();
map.set(1, "One");
map.set(2, "Two");
map.set(3, "Three");

console.log("=== With Map ===");

for (const [key, value] of map) {
    console.log(`${key}: ${value} (${typeof(key)})`);
}

console.log("=== With Object ===");

const fakeMap = {
    1: "One",
    2: "Two",
    3: "Three"
};

for (const key in fakeMap) {
    console.log(`${key}: ${fakeMap[key]} (${typeof(key)})`);
}

Kết quả:

=== With Map ===
1: One (number)
2: Two (number)
3: Three (number)
=== With Object ===
1: One (string)
2: Two (string)
3: Three (string)

11

Biên soạn các câu trả lời khác:

Vật

var test = {};

Khi sử dụng một số làm khóa của thuộc tính mới, số đó sẽ biến thành một chuỗi:

test[2300] = 'Some string';
console.log(test['2300']);
// Output: 'Some string'

Khi truy cập giá trị của thuộc tính bằng cách sử dụng cùng một số, số đó lại được chuyển thành chuỗi:

console.log(test[2300]);
// Output: 'Some string'

Tuy nhiên, khi lấy chìa khóa từ đối tượng, chúng sẽ không được chuyển trở lại thành số:

for (var key in test) {
    console.log(typeof key);
}
// Output: 'string'

Bản đồ

ECMAScript 6 cho phép sử dụng đối tượng Bản đồ ( tài liệu , so sánh với Đối tượng ). Nếu mã của bạn được hiểu cục bộ hoặc bảng tương thích ECMAScript 6 trông đủ xanh cho mục đích của bạn, hãy xem xét sử dụng Bản đồ:

var test = new Map();
test.set(2300, 'Some string');
console.log(test.get(2300));
// Output: 'Some string'

Không có chuyển đổi loại nào được thực hiện, tốt hơn và xấu hơn:

console.log(test.get('2300'));
// Output: undefined
test.set('2300', 'Very different string');
console.log(test.get(2300));
// Output: 'Some string'

4

Sử dụng một đối tượng thay vì một mảng. Mảng trong JavaScript không phải là mảng liên kết. Chúng là những đối tượng có phép thuật liên kết với bất kỳ thuộc tính nào có tên giống như số nguyên. Điều kỳ diệu đó không phải là thứ bạn muốn nếu bạn không sử dụng chúng như một cấu trúc giống mảng truyền thống.

var test = {};
test[2300] = 'some string';
console.log(test);

1
Chúng có thể là các mảng kết hợp, nhưng chỉ vì chúng cũng là các đối tượng có thể có các thuộc tính được đặt tên. Nhưng điều này chỉ làm cho mọi thứ trở nên khó hiểu một cách lố bịch, và do đó, các đối tượng tốt hơn nhiều để sử dụng.
Graza

Mảng không bao giờ có thể là Graza liên kết. Nếu bạn cố gắng sử dụng các khóa trong một mảng và sau đó lặp lại chúng, bạn sẽ nhận thấy rằng bạn cũng đang lặp lại tất cả các phương thức và thuộc tính mặc định của mảng -> không được mong muốn lắm.
Swizec Teller

@Swizec - chính xác tại sao tôi lại nói "khó hiểu một cách lố bịch". Bạn có thể sử dụng một mảng như một mảng kết hợp - đó là các cặp tên / giá trị, nhưng bạn sẽ không bao giờ muốn lặp lại chúng! (Tôi đã chỉ đơn giản là chỉ ra một công nghệ, chắc chắn không phải là điều tôi ở tất cả sẽ khuyên bạn nên làm)
Graza

có, nhưng khi lặp lại chúng không theo bất kỳ thứ tự cụ thể nào (tức là thứ tự không được đảm bảo), đó sẽ là điểm đánh số chúng, vì vậy nó tệ hơn rất nhiều so với việc chỉ gây nhầm lẫn.
Julix

3

Hãy thử sử dụng Đối tượng, không phải Mảng:

var test = new Object(); test[2300] = 'Some string';

3
Điều này chắc chắn là con đường để đi. Bằng cách này, bạn sẽ không tạo mảng dài 2300 mục nhập để lưu trữ một chuỗi.
Krystian

2
Mảng @Krystian JS là mảng giả. Chạy var a = []; a[Math.pow(2, 30)] = 'hello';và bạn sẽ không thấy trình duyệt / mức sử dụng bộ nhớ tăng hơn một gigabyte, nhưng bạn sẽ thấy a.lengthlà 1073741824. Máy ảo lưu trữ rõ ràng một số "mảng" bằng cách sử dụng một số cấu trúc dữ liệu khác, tôi đoán đơn giản là một bảng băm, ít nhất là nếu chúng đủ thưa thớt.
Andy

2

Nhận giá trị cho thuộc tính mảng kết hợp khi tên thuộc tính là số nguyên:

Bắt đầu với một mảng kết hợp trong đó tên thuộc tính là số nguyên:

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

Đẩy các mục vào mảng:

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

Lặp qua mảng và làm điều gì đó với giá trị thuộc tính.

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

Đầu ra của bảng điều khiển sẽ giống như sau:

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

Như bạn thấy, bạn có thể vượt qua giới hạn mảng kết hợp và có tên thuộc tính là một số nguyên.

LƯU Ý: Mảng kết hợp trong ví dụ của tôi là nội dung JSON bạn sẽ có nếu bạn tuần tự hóa một đối tượng Dictionary <string, string> [].



0

Đôi khi tôi sử dụng tiền tố cho các khóa của mình. Ví dụ:

var pre = 'foo',
    key = pre + 1234

obj = {};

obj[key] = val;

Bây giờ bạn không gặp bất kỳ vấn đề gì khi truy cập chúng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.