How to create a deep copy of a mutableStateList - arrays

I currently have this List of MutableStateLists:
val guessArray = List(5) { List(6) { "" }.toMutableStateList() }
I need to get a deep copy of each list by index, so something like:
var givenIndex = 0
val copiedArray = guessArray[givenIndex].//deep copy
copiedArray.forEach{} // some more code
What is the best way around this?
EDIT:
Went with this is the end:
val copyGuess = guessArray[currentRow].map { it }.toMutableList()

Related

How to stop original list from updating when cloned list is updated

I want to stop self.lineDetails from being updated when I update self.modifiedLineDetails.
self.modifiedLineDetails = [];
angular.forEach(self.lineDetails, function (value1, index1) {
var lineDetail = self.lineDetails[index1];
self.modifiedLineDetails.push(lineDetail)
});
console.log(self.lineDetails)
angular.forEach(self.modifiedLineDetails, function (value10, index10) {
var modifiedLineDetail = self.modifiedLineDetails[index10];
if (modifiedLineDetail.SelectedCustomers.length > 0) {
modifiedLineDetail.SelectedCustomers = 1;
} else {
modifiedLineDetail.SelectedCustomers = 0
}
});
console.log(self.modifiedLineDetails)
Previously I just assigned it like this self.modifiedLineDetails = self.lineDetails then I updated self.modifiedLineDetails but it wasn't working so I tried pushing it per line but self.lineDetails keeps updating.
You should clone an array and then modify your new array, one way to do this is using
spread operation ...
Here is the example of it:
var initialarray = [1,2,3,4];
var modification = [...initialarray];
modification.push(5);
console.log(initialarray);
console.log(modification);
Since the problem seems to be occurring because I was using angular. I researched and found angular.copy which creates a deep copy. The code below worked for me.
self.modifiedLineDetails = angular.copy(self.lineDetails);

passing objects in Angular

I know that passing objects in Angular is the same as passing objects in vanillaJs, what's stumping me is why my model is not being updated.
I have bins that contain packages. Given a packageId, I need to find the bin it's in, and remove the package from it.
vm.Bins = []; // bins of packages
vm.debinPackage = function (packageId) {
var bin = vm.getBin(packageId);
var packagge = vm.getPackage(packageId, bin.Packages);
vm.removePackageFromBin(packagge, bin);
};
vm.getBin = function (binId){
return $filter('filter')(vm.Bins, function(bin, index) {
return bin.Id == binId;
})[0];
};
vm.getPackage = function (packageId, packages) {
return $filter('filter')(packages, function(packageItem, index) {
return packageItem.Id == packageId;
})[0];
};
vm.removePackageFromBin = function (packagge, bin) {
bin = $filter('filter')(bin.Packages, function(packageItem, index) {
return packageItem.Id != packagge.Id;
});
};
.
<button ng-click="adminManifestVm.debinPackage(packageId)"></button>
{{ adminManifestVm.Bins }}
So, vm.Bins in my controller, and consequently adminManifestVm.Bins in my view don't update to reflect the package that's been removed from the bin.
i.e. this line:
vm.removePackageFromBin(packagge, bin);
does not actually result in an updated vm.Bins object.
I think the problem is that, when I get the bin object I use var as a holder:
var bin = vm.getBin(packageId);
and that it is somehow detached from my vm.Bins object.
but I can't figure out how to manipulate the actual object in vm.Bins.
I tried operating on the object directly, rather than through the var
vm.debinPackage = function (packageId) {
var binId = vm.getBinIdWithPackage(packageId);
var packagge = vm.getPackage(packageId, vm.getBin(binId).Packages);
vm.removePackageFromBin(packagge, vm.getBin(binId));
};
but not only does that not work, it starts to make my code unreadable.
How do I ensure that the bin object I am operating on is the one that's in vm.Bin, as opposed to some copy of it?
Have you tried using splice to remove the item from the array instead of reassigning the array with the filtered list?
vm.removePackageFromBin = function (package, bin) {
var idx = bin.indexOf(package);
bin.splice(idx, 1);
};

Spawning multiple coin node(s) using an array Swift SpriteKit

I use a function (shown below) to spawn a coin node in specific locations at random using an array.
Using this function, I am trying to incorporate more than one coin node (that are slightly different from one another) into this function so that multiple nodes can use this array to spawn and function just like the first coin node.
The problem that I have is that when I incorporate another node into this function or make a new but similar function for the 2nd node I get a Thread 1 SIGABERT error after the game crashes.
I currently have two separate functions for each node that are very similar, but with slight differences to accommodate each node.
func generateCoinZero() {
if(self.actionForKey("spawningCoinZero") != nil){return}
let coinTimerZero = SKAction.waitForDuration(2, withRange: 7)
let spawnCoinZero = SKAction.runBlock {
let coinZeroTexture = SKTexture(imageNamed: "coinZero")
self.coinZero = SKSpriteNode(texture: coinZeroTexture)
self.coinZero.physicsBody = SKPhysicsBody(circleOfRadius: self.coinZero.size.height / 12)
self.coinZero.physicsBody?.dynamic = false
self.coinZero.physicsBody?.allowsRotation = false
self.coinZero.zPosition = 1
self.coinZero.physicsBody?.categoryBitMask = ColliderType.coinZeroCategory
self.coinZero.physicsBody?.contactTestBitMask = ColliderType.playerCategory
self.coinZero.physicsBody?.collisionBitMask = 0
self.player.physicsBody?.categoryBitMask = ColliderType.playerCategory
self.player.physicsBody?.contactTestBitMask = 0
self.player.physicsBody?.collisionBitMask = ColliderType.boundary
var coinPositionZero = Array<CGPoint>()
coinPositionZero.append((CGPoint(x:250, y:139)))
coinPositionZero.append((CGPoint(x:790, y:298)))
coinPositionZero.append((CGPoint(x:225, y:208)))
coinPositionZero.append((CGPoint(x:220, y:237)))
let spawnLocationZero = coinPositionZero[Int(arc4random_uniform(UInt32(coinPositionZero.count)))]
let actionZero = SKAction.repeatActionForever(SKAction.moveToX(+self.xScale, duration: 2.0))
self.coinZero.runAction(actionZero)
self.coinZero.position = spawnLocationZero
self.addChild(self.coinZero)
print(spawnLocationZero)
}
let sequenceZero = SKAction.sequence([coinTimerZero, spawnCoinZero])
self.runAction(SKAction.repeatActionForever(sequenceZero), withKey: "spawningCoinZero")
}
func generateCoinTwo() {
if(self.actionForKey("spawnCoinTwo") != nil){return}
let coinTimerTwo = SKAction.waitForDuration(2, withRange: 7)
let spawnCoinTwo = SKAction.runBlock {
let coinTwoTexture = SKTexture(imageNamed: "coinTwo")
self.coinTwo = SKSpriteNode(texture: coinTwoTexture)
self.coinTwo.physicsBody = SKPhysicsBody(circleOfRadius: self.coinTwo.size.height / 12)
self.coinTwo.physicsBody?.dynamic = false
self.coinTwo.physicsBody?.allowsRotation = false
self.coinTwo.zPosition = 1
self.addChild(self.coinTwo)
var coinPositionTwo = Array<CGPoint>()
coinPositionTwo.append((CGPoint(x:250, y:139)))
coinPositionTwo.append((CGPoint(x:790, y:298)))
coinPositionTwo.append((CGPoint(x:225, y:208)))
coinPositionTwo.append((CGPoint(x:220, y:237)))
let spawnLocationTwo = coinPositionTwo[Int(arc4random_uniform(UInt32(coinPositionTwo.count)))]
let actionTwo = SKAction.repeatActionForever(SKAction.moveToX(+self.xScale, duration: 2.0))
self.coinTwo.runAction(actionTwo)
self.coinTwo.position = spawnLocationTwo
self.addChild(self.coinTwo)
print(spawnLocationTwo)
}
let sequenceTwo = SKAction.sequence([coinTimerTwo, spawnCoinTwo])
self.runAction(SKAction.repeatActionForever(sequenceTwo), withKey: "spawnCoinTwo")
}
OK, there are quite a lot of issues here, the main ones being the extreme duplication of code and having your generateCoin...-functions doing way too much. So here goes:
You state in the comments that the scene should have two coins spawning at different times at one of four possible positions. If the scene has two coins, then the scene has two coins. Let's just create these as properties and be done with it:
// Your two coin properties
let coin1 = coinNode()
let coin2 = coinNode()
// the function from which they are created
func coinNode() -> SKSpriteNode {
let coinNode = SKSpriteNode(imageNamed: "coinZero")
coinNode.physicsBody = SKPhysicsBody(circleOfRadius: coinNode.size.height / 2)
coinNode.physicsBody?.dynamic = false
coinNode.physicsBody?.allowsRotation = false
coinNode.zPosition = 1
coinNode.physicsBody?.categoryBitMask = ColliderType.coinZeroCategory
coinNode.physicsBody?.contactTestBitMask = ColliderType.playerCategory
coinNode.physicsBody?.collisionBitMask = 0 // A ColliderType.none would be lovely...
return coinNode
}
Now, these coins are not yet added to the scene nor do they have a proper position, this sounds like a fitting scope for another function:
func addCoin() {
let positions = [ CGPoint(x:250, y:139), CGPoint(x:790, y:298), CGPoint(x:225, y:208), CGPoint(x:220, y:237)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
if coin1.parent == nil {
coin1.position = position
addChild(coin1)
} else if coin2.parent == nil {
coin2.position = position
addChild(coin2)
}
}
Finally you want to have this function being called so do the following in your scene's init or setup:
let delay = SKAction.waitForDuration(1) // or however long you want it to be between each spawn
let addCoinCall = SKAction.runBlock({ self.addCoin() })
let spawnSequence = SKAction.sequence([delay, addCoinCall])
runAction(SKAction.repeatActionForever(spawnSequence))
You can't addChild twice, put addChild out of runBlock, and make sure that you are addChild once.
If you want put multiple coin, is better to copy your node and add on the scene.
You can create a node like coinZero out of function, and then inside the function do something like:
let coinToAdd = coinZero.copy()

Convert Array of objects to Array in angularjs

I have this data inside my controller form:
$scope.reports = [
{
departuredate:"2015-03-10",
routeline:"PASAY - CAGAYAN",
seatingtypescode:"ABS",
tickettripcode:"3",
tripcodetime:"16:30:00"
},
{
departuredate:"2015-03-10",
routeline:"PASAY - CAGAYAN",
seatingtypescode:"ABS",
tickettripcode:"3",
tripcodetime:"16:30:00"
}
];
The above data is array of objects, I want them to convert in array. I used this code below to convert them in array:
var details=[];
for(var index in $scope.reports){
var tripcode = $scope.reports[index].tickettripcode;
var dateOfDepature = $scope.reports[index].departuredate.split('-');
details.push(tripcode, dateOfDepature[2]);
}
if(details[tripcode][dateOfDeparture[2]]){
details[tripcode][dateOfDeparture[2]] = details[tripcode][dateOfDeparture[2]] +1;
}
else {
details[tripcode][dateOfDeparture[2]] =1;
}
The code is not working fine with me and I do not know why. I have a doubt if I am doing array manipulation in a right way. I have error dateOfDeparture is not defined. I already defined the dateOfDeparture so why I getting this error. I just wanted to get the output which looks like this:
details = Array (
[3] =>Array
(
[10] =>2
)
)
The [3]is tickettripcode and [10] is the day of depaturdate. The 2 means number of departuredate in that date.
Any help would be much appreciated.
This is the link of my fiddle : https://jsfiddle.net/n1bw2u36/
Thanks in advance!
Unfortunately there are a lot of things you should learn about javascript.
By the way, I would expect that you will get what you want with the code like this.
var reports = [
{
departuredate:"2015-03-10",
routeline:"PASAY - CAGAYAN",
seatingtypescode:"ABS",
tickettripcode:"3",
tripcodetime:"16:30:00"
},
{
departuredate:"2015-03-10",
routeline:"PASAY - CAGAYAN",
seatingtypescode:"ABS",
tickettripcode:"3",
tripcodetime:"16:30:00"
}
];
var table = {};
for (index=0; index<reports.length; index++){
var tripcode = reports[index].tickettripcode;
var dateOfDepature = reports[index].departuredate.split('-');
var date = dateOfDepature[2];
var map = table[tripcode];
if (map===undefined){
map = {};
table[tripcode] = map;
}
if (map[date]===undefined){
map[date] = 0;
}
map[date]++;
}
You can use "table" like this.
console.log(table);
console.log(table[3][10]);

AS3 Fastest way to merge multiple arrays

I'm trying to write a function where I can specify any amount of array, and the return value will be an array containing the contents of all of the specified arrays.
I've done this, but it seems like a really slow and ugly way of doing it:
var ar1:Array = [1,2,3,4,5,6,7,8,9];
var ar2:Array = ['a','b','c','d','e','f','g','h'];
function merge(...multi):Array
{
var out:String = "";
for each(var i:Array in multi)
{
out += i.join(',');
}
return out.split(',');
}
trace(merge(ar1, ar2));
Is there an inbuilt and more efficient / nice way of achieving this? The result does not need to be in the same order as the input - completely unsorted is fine.
You can use concat.
If the parameters specify an array, the elements of that array are concatenated.
var ar1:Array = [1,2,3,4,5,6,7,8,9];
var ar2:Array = ['a','b','c','d','e','f','g','h'];
var ar3:Array = ['i','j','k','l'];
var ar4 = ar1.concat(ar2, ar3); // or: ar1.concat(ar2).concat(ar3);
To make a single array out of a 2 dimensional array you can use this function:
private function flatten(arrays:Array):Array {
var result:Array = [];
for(var i:int=0;i<arrays.length;i++){
result = result.concat(arrays[i]);
}
return result;
}
// call
var ar4 = [ar1, ar2, ar3];
var ar5 = flatten(ar4);
You can also use varargs to merge multiple arrays:
private function merge(...arrays):Array {
var result:Array = [];
for(var i:int=0;i<arrays.length;i++){
result = result.concat(arrays[i]);
}
return result;
}
// call
var ar5 = merge(ar1, ar2, ar3);
I don't know if this method is faster than using loops, but it is a (fancy) quick way to merge 2 arrays. (and it works in Javascript and Actionscript)
var arr1:Array = [1,2,3,4,5]
var arr2:Array = [6,7,8,9,10]
arr1.push.apply(this, arr2); // merge
// arr1.push.call(this, arr2); // don't use this. see comment below
trace(arr1) // 1,2,3,4,5,6,7,8,9,10
function merge(...multi):Array
{
var res:Array = [];
for each(var i:Array in multi)
{
res = res.concat(i);
}
return res;
}
Didnt try it, but something like this would help you.

Resources