简体   繁体   中英

Javascript multidimensional array updating specific element

I have a string that has been converted into an 2D Array in js.

board = "...|.X.|...|"

It is used to represent a game board

each. represents a space

each | represents a row

each X represents a wall

EDIT: code below for the 2d array creation

var src= "...|.X.|...|";
board = src.split(/\|/g);

for (var i = 0; i < board.length; i++) {
var cells = board[i].split('');
for (var j = 0; j < cells.length; j++) {
    cells[j] = parseInt(cells[j]);
}
board[i][j] = cells;
console.log(board[1][1])
//returns 'X'

                    

when i access board[i][j] it returns correctly:

[0][0] = "."

[1][1] = "X"

[1][2] = "."

etc etc

I want to update the specific element with a string representing a piece. However when i insert into an element like so:

board[0][0] = "piece4"

The array returns in firebug as so:

board = "piece4|.X.|...|"

When it should look like:

board = ".piece4.|.X.|...|"

Why are elements [0][1] and [0][2] being overwritten? Am I not understanding arrays of array index access correctly in js?

I just had the same problem, but it had a more complex reason and I want to add it, in case someone finds this page searching for the same problem I had:

I had created and filled a 2-dimensional array like this:

var foo = Array(n).fill(Array(n).fill(0));

which creates a 2-dimensional n*n array filled with zeroes.

Now when I tried to overwrite a cell like this

foo[1][1] = 1;

I ended up with these values:

[[0,1,0],
 [0,1,0],
 [0,1,0]]

which is really surprising IMHO.

The reason for this was, that there has only been one row, which had internally been referenced three times. So when I changed the first index in "the second" row, it effectively changed all rows.

Bottom line: don't use Array.fill to create multi-dimensional arrays!

PROBLEM:

I'm betting that you have a one-dimensional array with strings stored in each. So your array actually looks like:

array (
    [0] => '...',
    [1] => '.X.',
    [2] => '...'
)

When this is what you want:

array (
    [0] => array (
        [0] => '.',
        [1] => '.',
        [2] => '.'
    ),
    [1] => array (
        [0] => '.',
        [1] => 'X',
        [2] => '.'
    ),
    [2] => array (
        [0] => '.',
        [1] => '.',
        [2] => '.'
    )
)


SOLUTION:

When constructing your 2D array, make sure you explicitly declare each entry in board as an array. So to construct it, your code might look something like this:

board = new Array();
rows = 3;
for (var i = 0; i < rows; i++)
    board[i] = new Array('.', '.', '.');

I ran into a similar problem. So after reading a lot... this finally suited my needs.

myArr = [1,1,1];
var arr = new Array();

for (var i = 0; i < 10; i++) {
  arr[i] = Array.from(myArr);
}

//lets edit 3 positions
arr[0][1]= -1;
arr[3][2]= 100;
arr[8][0] = 8080;


for(var i=0; i<10; i++){
console.log(i + " === " + arr[i]);
}

OUTPUT: if you noticed only the edited index values changed... nothing else

0 === 1,-1,1  <---
1 === 1,1,1
2 === 1,1,1
3 === 1,1,100 <---
4 === 1,1,1
5 === 1,1,1
6 === 1,1,1
7 === 1,1,1
8 === 8080,1,1 <---
9 === 1,1,1

The situation and solution given above is pretty simple. The issue of updating specific values in a list of objects (often referred to as an array, but that's a discussion for a different time) has more practical and industrial application. The problem you tend to run into is thinking that looking at a value in a specific cell, eg my_array[0][0] returns 'some value' will also let you change that value through an assignment eg my_array[0][0] = 'new value'. You will find that depending on how you defined your array, the change shows in the same row across the columns, not what you are needing. Look at the example code as an illustration of creating, and managing a multidimensional list of objects (array).

<html>
<head>
<title>JavaScript Object List/Array</title>
<script>
//Make a JavaScript array that can manage data of inventory between different locations over time.
var list_of_brands = ["BMW","Harley Davidson","Honda","Kawasaki"];
var list_of_locations = ["Dayton","Cincinnati"];

//a month of data
var DAYS_IN_A_MONTH = 30;
var calendar = [];
for(day_of_sales = 1; day_of_sales <= DAYS_IN_A_MONTH; day_of_sales++){

  //hold your locations
  var shop_location = [];//You need to create a new array for each day - that's part of the trick!

  for(location_index = 0;location_index < list_of_locations.length;location_index++){

  //set up some starting inventory
  var inventory = [];//You need to create a new array for each location - that's part of the trick!

      for(brand_index = 0; brand_index < list_of_brands.length; brand_index++){ 

        inventory[list_of_brands[brand_index]] = {"brand": list_of_brands[brand_index], "on_hand": 10,"sold": 0};

      };//end inventory loop

      shop_location[list_of_locations[location_index]] = {"city":list_of_locations[location_index],inventory};

  }//end location loop

  calendar[day_of_sales] = {"Day": day_of_sales, shop_location};

}//end calendar loop

//check your work
console.log('calendar:'); console.log(calendar);
console.log('shop_location:'); console.log(shop_location);
console.log('specific information: '); console.log(calendar[1].shop_location["Dayton"].inventory['BMW'].brand);//returns 'BMW'
console.log('change Dayton.BMW information: '); console.log(calendar[1].shop_location["Dayton"].inventory['BMW'].brand="Triumph");//change value
console.log('check work (Dayton.BMW): '); console.log(calendar[1].shop_location["Dayton"].inventory['BMW'].brand);//check work - PASS
console.log('check work (Cincinnati.BMW): '); console.log(calendar[1].shop_location["Cincinnati"].inventory["BMW"].brand);//check work other location - PASS!!

//Make some lasting and specific changes
console.log("Now make a change in the month's value over showing a sale on the 13th");
var sale_date = 13;
console.log("date of sale " + sale_date + "th");

var original_number_on_hand = calendar[sale_date].shop_location["Dayton"].inventory["BMW"].on_hand;
console.log("original_number_on_hand on that date: " + original_number_on_hand);

var number_of_units_sold = 3;
console.log("number_of_units_sold on that date: " + number_of_units_sold);

var new_inventory_level = original_number_on_hand - number_of_units_sold;
console.log("new_inventory_level: " + new_inventory_level);

for(date_index = sale_date; date_index  <= DAYS_IN_A_MONTH; date_index ++){  
  calendar[date_index].shop_location["Dayton"].inventory["BMW"].sold = number_of_units_sold;
  calendar[date_index].shop_location["Dayton"].inventory["BMW"].on_hand = new_inventory_level;
}

console.log("Show change in inventory");
  console.log(list_of_locations[0]+" has " + calendar[10].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[10].shop_location["Cincinnati"].inventory["BMW"].on_hand);
  console.log(list_of_locations[0]+" has " + calendar[11].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[11].shop_location["Cincinnati"].inventory["BMW"].on_hand);
  console.log(list_of_locations[0]+" has " + calendar[12].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[12].shop_location["Cincinnati"].inventory["BMW"].on_hand);
  console.log(list_of_locations[0]+" has " + calendar[13].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[13].shop_location["Cincinnati"].inventory["BMW"].on_hand);
  console.log(list_of_locations[0]+" has " + calendar[14].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[14].shop_location["Cincinnati"].inventory["BMW"].on_hand);
  console.log(list_of_locations[0]+" has " + calendar[15].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[15].shop_location["Cincinnati"].inventory["BMW"].on_hand);
  console.log(list_of_locations[0]+" has " + calendar[16].shop_location["Dayton"].inventory["BMW"].on_hand + " " + list_of_locations[1]+" has " + calendar[16].shop_location["Cincinnati"].inventory["BMW"].on_hand);

  //add new items to a shop's inventory
var inventory_2 =[];
for(brand_index = 0; brand_index < list_of_brands.length; brand_index++){ 

  inventory_2[list_of_brands[brand_index]] = {"brand": list_of_brands[brand_index], "on_hand": 10,"sold": 0};

};//end inventory loop
console.log("show inventory_2");console.log(inventory_2);
console.log("add inventory");inventory_2["Indian"] = {"brand": "Indian", "on_hand": 10,"sold": 0};
console.log("show updated inventory_2");console.log(inventory_2);

</script>
</head>
<body>
  <p>look in the JavaScript console for output</p>
</body>
</html>

An other way to create a 2D array in javascript is to use Array.from function

  var 2Darr =  Array.from(Array(5), () => {
                 return new Array(5).fill(0)
             })

This will create a 5 x 5 array completely filled with 0. Array.from takes two parameters, the first one is an javascript iterable Object to extract the array from, the second one is an optional callback where we can specify something to apply to the array elements.

Accessing the element can be done simply like in other languages.

Two remarks here:

  1. Arrays start with index 0 in every dimension.
  2. If you access a string as a 2D array, every element is a char rather than a string.

So if you write board[0][0] = 'X'; then you get the right behavior (and that changes the first character of the string, not the second).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM