Phần tử mảng trao đổi Javascript


228

Có cách nào đơn giản hơn để trao đổi hai phần tử trong một mảng không?

var a = list[x], b = list[y];
list[y] = a;
list[x] = b;

Câu trả lời:


412

Bạn chỉ cần một biến tạm thời.

var b = list[y];
list[y] = list[x];
list[x] = b;

Chỉnh sửa câu trả lời hàng đầu 10 năm sau với rất nhiều việc áp dụng ES6 trong vành đai của chúng tôi:

Đưa ra mảng arr = [1,2,3,4], bạn có thể trao đổi giá trị trong một dòng ngay bây giờ như sau:

[arr[0], arr[1]] = [arr[1], arr[0]];

Điều này sẽ tạo ra các mảng [2,1,3,4]. Đây là nhiệm vụ hủy hoại .


2
Ngay cả khi không sử dụng Phân công hủy cấu trúc ECMAScript 6, thực sự có thể đạt được sự hoán đổi đồng thời mà không làm ô nhiễm phạm vi hiện tại với một biến tạm thời: a = [b, b = a][0];như được chỉ ra bởi @Jan Mặc dù tôi vẫn thấy mình sử dụng cách tiếp cận biến tạm thời như ngôn ngữ chéo (ví dụ: C / C ++ ) và cách tiếp cận đầu tiên thường xuất hiện trong tâm trí tôi.
Ultimater

3
Bạn có thể trao đổi tại chỗ (đột biến) với es6 như những người khác hiển thị bên dưới:[ list[y], list[x] ] = [ list[x], list[y] ];
protoEveachion

[arr[0], arr[1]] = [arr[1], arr[0]]chỉ sản xuất [2, 1]mà không có phần còn lại của mảng
Yerko Palma

8
@YerkoPalma - biểu thức trả về [2.1], nhưng mảng ban đầu sẽ bị biến đổi thành [2,1,3,4]
danbars

111

Nếu bạn muốn một biểu thức, sử dụng javascript gốc, hãy nhớ rằng giá trị trả về từ thao tác ghép có chứa (các) phần tử đã bị xóa.

var A = [1, 2, 3, 4, 5, 6, 7, 8, 9], x= 0, y= 1;
A[x] = A.splice(y, 1, A[x])[0];
alert(A); // alerts "2,1,3,4,5,6,7,8,9"

Biên tập:

Điều [0]cần thiết ở cuối biểu thức là Array.splice()trả về một mảng và trong tình huống này, chúng tôi yêu cầu phần tử đơn trong mảng được trả về.


3
mối nối trả về một mảng. Vì vậy, trong ví dụ của bạn, sau thao tác hoán đổi, mảng của bạn thực sự trông như sau: [[2], 1, 3, 4, 5, 6, 7, 8, 9]
JPot

1
A [x] = A.splice (y, 1, A [x]) [0]; ? trong mootools Array.im Hiện ({exchange: function (x, y) {this [y] = this.splice (x, 1, this [y]) [0];}});
ken

Xác nhận, [0] bị thiếu.
Johann Philipp Strathausen

tốt và ngắn, nhưng như @aelgoa đã nói, hầu như chậm thì hoán đổi đơn giản
ofir_aghai

75

Điều này có vẻ ổn ....

var b = list[y];
list[y] = list[x];
list[x] = b;

Howerver sử dụng

var b = list[y];

có nghĩa là một biến b sẽ xuất hiện trong phần còn lại của phạm vi. Điều này có khả năng có thể dẫn đến rò rỉ bộ nhớ. Không thể, nhưng vẫn tốt hơn để tránh.

Có lẽ một ý tưởng tốt để đưa điều này vào Array.prototype.swap

Array.prototype.swap = function (x,y) {
  var b = this[x];
  this[x] = this[y];
  this[y] = b;
  return this;
}

có thể được gọi là như:

list.swap( x, y )

Đây là một cách tiếp cận rõ ràng để tránh rò rỉ bộ nhớDRY .


Tôi cũng thích điều này. Array.im Hiện ({exchange: function (x, y) {x = this [x]; this [x] = this [y]; this [y] = x; return this;}});
ken

1
Cái này đẹp đấy. Có thể một số giới hạn kiểm tra? Array.prototype.swap = function (x,y) { if (x >= 0 && x < this.length && y >= 0 && y < this.length) { var b = this[x]; this[x] = this[y]; this[y] = b; } return this; };
David R.

@DavidR. Kiểm tra giới hạn là không cần thiết và không cần thiết. Người gọi có mọi thứ cần thiết để thực hiện kiểm tra như vậy nếu muốn, mặc dù trong hầu hết các trường hợp bạn đã biết x và y nằm trong giới hạn bởi vì bạn đang ở trong một vòng lặp nào đó.
Neil

6
Bạn không thể tránh khỏi "rò rỉ bộ nhớ tiềm năng" bằng cách chỉ gói nó trong một chức năng?
Carcigenicate 16/2/2016

3
Để tránh rủi ro "làm phẳng" tiềm năng, tôi sẽ không chạm vào chuỗi nguyên mẫu của bất kỳ loại tích hợp nào.
AaronDancer

54

Theo một số người ngẫu nhiên trên Metafilter , "Các phiên bản gần đây của Javascript cho phép bạn thực hiện các giao dịch hoán đổi (trong số những thứ khác) gọn gàng hơn nhiều:"

[ list[x], list[y] ] = [ list[y], list[x] ];

Các thử nghiệm nhanh của tôi cho thấy mã Pythonic này hoạt động rất tốt trong phiên bản JavaScript hiện đang được sử dụng trong "Tập lệnh Google Apps" (".ss"). Than ôi, các thử nghiệm tiếp theo cho thấy mã này đưa ra một "Uncaught ReferenceError: bên trái không hợp lệ trong bài tập." trong bất kỳ phiên bản JavaScript nào (".js") được Google Chrome sử dụng Phiên bản 24.0.1312.57 m.


2
Đây là một phần của đề xuất ES6: nó chưa được chính thức hóa, do đó, nó hoàn toàn không nên được coi là hoạt động ở mọi nơi (sẽ thật tuyệt vời nếu nó đã ...).
Isiah Meadows

2
Nó hoạt động trong phiên bản firefox mới nhất hiện tại (39.0.3).
Jamie

2
Nó hoạt động trong phiên bản Chrome 54.0.2840.71 và các phiên bản trước đó. Ngoài ra, đây phải là mã đã nhận của bạn nếu bạn sử dụng bộ chuyển mã ES6 như babel .
amoebe

3
Yêu giải pháp này. Sạch sẽ, như dự định. Quá tệ, câu hỏi đã được hỏi 9 năm trước ...
DavidsKanal 23/07/18

2
nó đã được chuẩn hóa trong es6 và tính năng này được gọi là phá hủy.
AL-zami

29

Chà, bạn không cần phải đệm cả hai giá trị - chỉ một:

var tmp = list[x];
list[x] = list[y];
list[y] = tmp;

13
'tmp' của bạn nghe có vẻ hợp lý hơn để sử dụng sau đó 'b'
mtasic85

@ofir_aghai vâng, bạn đúng: 10+ năm trước, một câu trả lời khác đã được đăng 22 giây trước câu này (12: 14: 16Z so với 12: 14: 38Z) ...
Marc Gravell

trong ngày thường, tôi đã gắn bó với nó. nhưng chỉ vì vấn đề giây và sự tôn trọng trong 10 năm của bạn tiếp tục ở đây ;-)
ofir_aghai

xin lỗi nó không cho phép tôi thay đổi phiếu bầu .. "
Phiếu

22

Bạn có thể trao đổi các phần tử trong một mảng theo cách sau:

list[x] = [list[y],list[y]=list[x]][0]

Xem ví dụ sau:

list = [1,2,3,4,5]
list[1] = [list[3],list[3]=list[1]][0]
//list is now [1,4,3,2,5]

Lưu ý: nó hoạt động theo cùng một cách cho các biến thông thường

var a=1,b=5;
a = [b,b=a][0]

6
Điều này rất giống với cách chính xác tiêu chuẩn để làm điều này trong ES6 (phiên bản tiếp theo của JavaScript) : [list[x], list[y]] = [list[y], list[x]];.
Isiah Meadows

1
Điều này không có gì để chúng ta hoán đổi mảng ES6 bằng cách hủy cấu trúc. Đây chỉ là một cách sử dụng thông minh của quy trình làm việc JS. Một mô hình trao đổi đẹp nếu bạn sử dụng mã hóa nội tuyến thường xuyên, chẳng hạn nhưthis[0] > this[1] && (this[0] = [this[1],this[1]=this[0]][0]);
Redu

18

Với các giá trị số, bạn có thể tránh một biến tạm thời bằng cách sử dụng bitwise xor

list[x] = list[x] ^ list[y];
list[y] = list[y] ^ list[x];
list[x] = list[x] ^ list[y];

hoặc tổng số học (lưu ý rằng điều này chỉ hoạt động nếu x + y nhỏ hơn giá trị tối đa cho loại dữ liệu)

list[x] = list[x] + list[y];
list[y] = list[x] - list[y];
list[x] = list[x] - list[y];

2
Là darth như trong vader? +1
krosenvold

7
Có gì đó không đúng ở đây. Không list[y] = list[x] - list[x];chỉ tương đương với list[y] = 0;?
ErikE

3
Thủ thuật xor cũng thất bại khi x = y - nó đặt danh sách [x] thành 0, khi bạn có thể mong đợi nó giữ danh sách [x] giá trị ban đầu.
David Cary

1
Về mặt kỹ thuật, bạn tạo một giá trị tạm thời mà bạn không di chuyển nó ra ngoài khu vực có liên quan của mảng.
Đánh dấu Smit

1
Không đơn giản hơn, không hiệu quả hơn, không chung chung.
LoganMzz

17

Điều này không tồn tại khi câu hỏi được hỏi, nhưng ES2015 đã giới thiệu tính năng phá hủy mảng, cho phép bạn viết nó như sau:

let a = 1, b = 2;
// a: 1, b: 2
[a, b] = [b, a];
// a: 2, b: 1

14
Để trao đổi như thế này trong mảng:[list[x], list[y]] = [list[y], list[x]];
Stromata

15

Để hoán đổi hai phần tử liên tiếp của mảng

array.splice(IndexToSwap,2,array[IndexToSwap+1],array[IndexToSwap]);

13

Thông báo từ http://www.greywyvern.com/?post=265

var a = 5, b = 9;    
b = (a += b -= a) - b;    
alert([a, b]); // alerts "9, 5"

1
Nếu bạn bọc cái này trong một swap(a, b)chức năng, bạn không cần phải lo lắng về khả năng đọc.
AccidentalTaylorExpansion

1
Chỉ hoạt động cho số nguyên
Redu

Điều này có lẽ tối ưu hóa kém. Một trình biên dịch có thể phát hiện ra nó như là một "thành ngữ hoán đổi", nhưng không thể chắc chắn về các hiệu ứng trừ khi có thể chắc chắn rằng cả hai loại đều là số nguyên và cũng không phải là bí danh .
mwfearnley

10

Điều gì về Desturationuring_assocation

var arr = [1, 2, 3, 4]
[arr[index1], arr[index2]] = [arr[index2], arr[index1]]

cũng có thể được mở rộng đến

[src order elements] => [dest order elements]

9

Xem xét một giải pháp như vậy mà không cần xác định biến thứ ba:

function swap(arr, from, to) {
  arr.splice(from, 1, arr.splice(to, 1, arr[from])[0]);
}

var letters = ["a", "b", "c", "d", "e", "f"];

swap(letters, 1, 4);

console.log(letters); // ["a", "e", "c", "d", "b", "f"]

Lưu ý: Bạn có thể muốn thêm các kiểm tra bổ sung, ví dụ về độ dài mảng. Giải pháp này có thể thay đổi được nên swaphàm không cần trả về một mảng mới, nó chỉ thực hiện đột biến trên mảng được truyền vào.


Ngoài ra, toán tử lây lan cũng có thể được sử dụng:arr.splice(from, 1, arr.splice(to, 1, ...arr[from]))
Orkun Tuzel

7

Bạn có thể trao đổi bất kỳ số lượng đối tượng hoặc nghĩa đen, thậm chí các loại khác nhau, bằng cách sử dụng một chức năng nhận dạng đơn giản như thế này:

var swap = function (x){return x};
b = swap(a, a=b);
c = swap(a, a=b, b=c);

Đối với vấn đề của bạn:

var swap = function (x){return x};
list[y]  = swap(list[x], list[x]=list[y]);

Điều này hoạt động trong JavaScript vì nó chấp nhận các đối số bổ sung ngay cả khi chúng không được khai báo hoặc sử dụng. Các bài tập a=b, vv, xảy ra sau khi ađược truyền vào hàm.


Hackish ... nhưng bạn có thể làm tốt hơn một lần, nếu bạn chỉ sử dụng chức năng một lần : list[y] = (function(x){return x})(list[x],list[x]=list[y]);. Hoặc, nếu bạn quan tâm đến ES6 (phiên bản tiếp theo của JS), nó cực kỳ dễ dàng : [list[x], list[y]] = [list[y], list[x]. Tôi rất vui vì họ đang thêm một số khía cạnh chức năng và dựa trên lớp vào phiên bản tiếp theo của JavaScript.
Isiah Meadows

6

Đối với hai hoặc nhiều yếu tố (số cố định)

[list[y], list[x]] = [list[x], list[y]];

Không yêu cầu biến tạm thời!

Tôi đã suy nghĩ về việc đơn giản gọi list.reverse().
Nhưng sau đó tôi nhận ra nó chỉ hoạt động như trao đổi khilist.length = x + y + 1 .

Đối với số lượng phần tử thay đổi

Tôi đã xem xét các cấu trúc Javascript hiện đại khác nhau cho hiệu ứng này, bao gồm Bản đồbản đồ , nhưng thật đáng buồn là không có kết quả nào trong mã nhỏ gọn hơn hoặc nhanh hơn so với cách xây dựng dựa trên vòng lặp, lỗi thời này:

function multiswap(arr,i0,i1) {/* argument immutable if string */
    if (arr.split) return multiswap(arr.split(""), i0, i1).join("");
    var diff = [];
    for (let i in i0) diff[i0[i]] = arr[i1[i]];
    return Object.assign(arr,diff);
}

Example:
    var alphabet = "abcdefghijklmnopqrstuvwxyz";
    var [x,y,z] = [14,6,15];
    var output = document.getElementsByTagName("code");
    output[0].innerHTML = alphabet;
    output[1].innerHTML = multiswap(alphabet, [0,25], [25,0]);
    output[2].innerHTML = multiswap(alphabet, [0,25,z,1,y,x], [25,0,x,y,z,3]);
<table>
    <tr><td>Input:</td>                        <td><code></code></td></tr>
    <tr><td>Swap two elements:</td>            <td><code></code></td></tr>
    <tr><td>Swap multiple elements:&nbsp;</td> <td><code></code></td></tr>
</table>


5

Có một cách hoán đổi thú vị:

var a = 1;
var b = 2;
[a,b] = [b,a];

(Cách ES6)


5
đối với một mảng, nó còn hơn thế nữavar a= [7,8,9,10], i=2, j=3;[a[i],a[j]] = [a[j],a[i]];
caub

4
var a = [1,2,3,4,5], b=a.length;

for (var i=0; i<b; i++) {
    a.unshift(a.splice(1+i,1).shift());
}
a.shift();
//a = [5,4,3,2,1];

3

Đây là một lớp lót không đột biến list:

let newList = Object.assign([], list, {[x]: list[y], [y]: list[x]})

(Sử dụng các tính năng ngôn ngữ không có sẵn trong năm 2009 khi câu hỏi được đăng!)


1

Đây là một phiên bản nhỏ gọn hoán đổi giá trị tại i1 với i2 trong mảng

arr.slice(0,i1).concat(arr[i2],arr.slice(i1+1,i2),arr[i1],arr.slice(i2+1))

Đó là ít hiệu quả hơn phương pháp biến tạm thời. Bạn thực sự trả lại một mảng đã sửa đổi được cắt ba lần và nối với nhau bằng hai đối tượng giữa ba mảng được cắt. Bạn thực sự cần nhiều hơn hai lần bộ nhớ so với mức cần thiết để lấy giá trị chỉ đơn giản là gán cho mảng (không có cái nào được thực hiện tại chỗ).
Isiah Meadows

1

Đây là một biến thể đầu tiên kiểm tra nếu chỉ mục tồn tại trong mảng:

Array.prototype.swapItems = function(a, b){
    if(  !(a in this) || !(b in this) )
        return this;
    this[a] = this.splice(b, 1, this[a])[0];
    return this;
}

Hiện tại nó sẽ chỉ trả về thisnếu chỉ mục không tồn tại, nhưng bạn có thể dễ dàng sửa đổi hành vi khi không thành công


1

Hoán đổi phần tử đầu tiên và cuối cùng trong một mảng mà không có biến tạm thời hoặc phương thức hoán đổi ES6 [a, b] = [b, a]

[a.pop(), ...a.slice(1), a.shift()]


1

Giải pháp bản in sao chép mảng thay vì làm biến đổi cái hiện có

export function swapItemsInArray<T>(items: T[], indexA: number, indexB: number): T[] {
  const itemA = items[indexA];

  const clone = [...items];

  clone[indexA] = clone[indexB];
  clone[indexB] = itemA;

  return clone;
}

0

Chỉ để giải trí, một cách khác mà không sử dụng bất kỳ biến phụ nào sẽ là:

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// swap index 0 and 2
arr[arr.length] = arr[0];   // copy idx1 to the end of the array
arr[0] = arr[2];            // copy idx2 to idx1
arr[2] = arr[arr.length-1]; // copy idx1 to idx2
arr.length--;               // remove idx1 (was added to the end of the array)


console.log( arr ); // -> [3, 2, 1, 4, 5, 6, 7, 8, 9]


0

Vì lợi ích của sự ngắn gọn, đây là phiên bản một lớp lót xấu xí chỉ hơi xấu xí hơn tất cả những gì được ghép và cắt ở trên. Câu trả lời được chấp nhận thực sự là cách để đi và cách dễ đọc hơn.

Được:

var foo = [ 0, 1, 2, 3, 4, 5, 6 ];

nếu bạn muốn trao đổi các giá trị của hai chỉ số (a và b); sau đó điều này sẽ làm điều đó:

foo.splice( a, 1, foo.splice(b,1,foo[a])[0] );

Ví dụ: nếu bạn muốn trao đổi 3 và 5, bạn có thể thực hiện theo cách này:

foo.splice( 3, 1, foo.splice(5,1,foo[3])[0] );

hoặc là

foo.splice( 5, 1, foo.splice(3,1,foo[5])[0] );

Cả hai đều cho kết quả như nhau:

console.log( foo );
// => [ 0, 1, 2, 5, 4, 3, 6 ]

#splicehatersarepunks :)


0

Nếu bạn không muốn sử dụng biến temp trong ES5, đây là một cách để trao đổi các phần tử mảng.

var swapArrayElements = function (a, x, y) {
  if (a.length === 1) return a;
  a.splice(y, 1, a.splice(x, 1, a[y])[0]);
  return a;
};

swapArrayElements([1, 2, 3, 4, 5], 1, 3); //=> [ 1, 4, 3, 2, 5 ]

Bằng cách này, thay vì tạo một biến tạm thời, bạn đang tạo 2 mảng mới khi a.splicetrả về một mảng với các phần tử bị loại bỏ. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/,
XCS

Có cách nào để chúng ta có thể làm điều đó tốt hơn không? @Cristy
venkat7668

Câu trả lời được chấp nhận là thẳng về phía trước một. Điều này sẽ hữu ích khi bạn có giới hạn về số lượng khai báo biến (chủ yếu là mục đích phỏng vấn :)). Nhưng không hiệu quả bộ nhớ như bạn đã đề cập. @Cristy
venkat7668

Cá nhân tôi nghĩ rằng đó là một thực hành xấu và không nên được khuyến khích cho người mới bắt đầu. Nó cũng rất khó đọc.
XCS

0

thử chức năng này ...

$(document).ready(function () {
        var pair = [];
        var destinationarray = ['AAA','BBB','CCC'];

        var cityItems = getCityList(destinationarray);
        for (var i = 0; i < cityItems.length; i++) {
            pair = [];
            var ending_point = "";
            for (var j = 0; j < cityItems[i].length; j++) {
                pair.push(cityItems[i][j]);
            }
            alert(pair);
            console.log(pair)
        }

    });
    function getCityList(inputArray) {
        var Util = function () {
        };

        Util.getPermuts = function (array, start, output) {
            if (start >= array.length) {
                var arr = array.slice(0);
                output.push(arr);
            } else {
                var i;

                for (i = start; i < array.length; ++i) {
                    Util.swap(array, start, i);
                    Util.getPermuts(array, start + 1, output);
                    Util.swap(array, start, i);
                }
            }
        }

        Util.getAllPossiblePermuts = function (array, output) {
            Util.getPermuts(array, 0, output);
        }

        Util.swap = function (array, from, to) {
            var tmp = array[from];
            array[from] = array[to];
            array[to] = tmp;
        }
        var output = [];
        Util.getAllPossiblePermuts(inputArray, output);
        return output;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


0

var arr = [1, 2];
arr.splice(0, 2, arr[1], arr[0]);
console.log(arr); //[2, 1]


1
Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn.
Alessio

-1

Sử dụng ES6 có thể làm điều đó như thế này ...

Hãy tưởng tượng bạn có 2 mảng này ...

const a = ["a", "b", "c", "d", "e"];
const b = [5, 4, 3, 2, 1];

và bạn muốn trao đổi các giá trị đầu tiên:

const [a0] = a;
a[0] = b[0];
b[0] = a0;

và giá trị:

a; //[5, "b", "c", "d", "e"]
b; //["a", 4, 3, 2, 1]

-2
Array.prototype.swap = function(a, b) {
  var temp = this[a];
  this[a] = this[b];
  this[b] = temp;
};

Sử dụng:

var myArray = [0,1,2,3,4...];
myArray.swap(4,1);

1
Không cần phải thô lỗ. Ngoài ra, việc mở rộng Arraynguyên mẫu không phải là một phần của những gì được yêu cầu - nó có thể gây nhầm lẫn nhiều hơn là không tốt.
Mathias Lykkegaard Lorenzen

Làm thế nào để thể hiện rằng một số câu trả lời là điên rồ và mở rộng nguyên mẫu mảng sẽ có và thêm một trả về điều này sẽ làm cho chuỗi có thể ...
user2472643

2
Bạn đang thể hiện nó là "cách chính xác". Nó có thể cho ấn tượng sai. Thay vào đó, tôi sẽ đề nghị đề cập đến những gì bạn đang làm (mở rộng nguyên mẫu) và làm thế nào nó hữu ích, chính xác như bạn vừa mô tả với tôi.
Mathias Lykkegaard Lorenzen

1
Gotcha, xin lỗi tư thế đĩnh đạc của tôi không phải là về cặp đôi ^ _ ^
user2472643

2
Bạn là người duy nhất mô tả một vấn đề với bối cảnh của câu trả lời ... trước hết nên cho điểm tiêu cực cho những câu trả lời không hoạt động. Thứ hai, đây là một câu trả lời tốt với cách sử dụng tao nhã không gây ra xung đột. Thẩm phán mã không giao hàng. Ngoài ra trong câu trả lời của tôi nếu bạn gỡ nó xuống và loại trừ phần mở rộng nguyên mẫu, nó sẽ trở thành câu trả lời giống như câu trả lời được bình chọn nhiều nhất, vì vậy thực tế là đây là -6 cho thấy sự thiếu suy nghĩ từ những người đã bỏ phiếu. Và đã được đăng vài tháng trước câu trả lời hàng đầu ... vì vậy điều này nghe có vẻ như không phải là một cuộc thi về mã.
dùng2472643

-3

Nếu cần hoán đổi các yếu tố đầu tiên và cuối cùng:

array.unshift( array.pop() );

Mã này là thiếu sót. Nó lấy phần tử cuối cùng của mảng rồi đặt nó ở đầu, không phải là hoán đổi. Mã này làm điều này: [1, 2, 3] => [3, 1, 2]thay vì [1, 2, 3] => [3, 2, 1].
David Archibald
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.