Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I am trying to push a shuffled string array to my scope variable, but some how its throwing error for duplicate array values. This never happened before.

Below is my code snippet. You can check the console for error:

var app = angular.module('ABCD', []);
app.controller('ABCDController', ['$scope',
  function($scope) {
    $scope.start_word = ['C', 'A', 'T'];
    $scope.word = [
      ['C', 'A', 'T']
    ];
    $scope.shuffle = function() {
      var shuffle_word = Shuffle($scope.word[0]);
      console.log("SHUFFLED VARIABLE: " + shuffle_word);
      console.log("SCOPE VARIABLE: " + $scope.word);
      $scope.word.push(shuffle_word);
    };
  }
]);

function Shuffle(o) {
  for (var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
  return o;
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<div ng-app="ABCD">
  <div ng-controller="ABCDController">
    <button class="btn btn-primary" ng-click="shuffle()">Shuffle</button>
    <p>START WORD: {{start_word}}</p>
    <p ng-repeat="(key,value) in word">SHUFFLED WORD: {{value}}</p>
  </div>
</div>

My error is, when I try to push new shuffled value into the array, it changes all values to the new. For eg:

Initial array:

console.log($scope.word); OUTPUT: [['C','A','T']]

After push:

console.log($scope.word) OUTPUT: [['T','C','T'],['T','C','T']]

share|improve this question
    
ng-repeat="(key, val) in x" is the syntax for objects.. you want ng-repeat="letter in word" for arrays. – tymeJV Mar 2 '15 at 17:49
    
My problem is when I try to push my shuffled value in the array, it changes the previous one, because of which I am getting duplicate error – ntechi Mar 2 '15 at 17:51
    
So do you want a history of entirely new shuffled words for each time you click Shuffle? Or only the most recent result? – ryanyuyu Mar 2 '15 at 17:52
1  
Add a track by clause: ng-repeat="letter in word track by $index" – tymeJV Mar 2 '15 at 17:53
    
I only want newly added value to be changed, in my case entire scope array is getting changed. Please refer my question again. I edited it with more description – ntechi Mar 2 '15 at 17:55
up vote 2 down vote accepted

You're shuffling the original word and creating two values that are the same. Use a temporary copy of the word as shown below. Edit: This answer shows the trick of copying an array.

var app = angular.module('ABCD', []);
app.controller('ABCDController', ['$scope',
  function($scope) {
    $scope.start_word = ['C', 'A', 'T'];
    $scope.word = [
      ['C', 'A', 'T']
    ];
    $scope.shuffle = function() {
      var tmpWord = $scope.word[0].slice(); // create a copy
      var shuffle_word = Shuffle(tmpWord);
      console.log("SHUFFLED VARIABLE: " + shuffle_word);
      console.log("SCOPE VARIABLE: " + $scope.word);
      $scope.word.push(shuffle_word);
      console.log($scope.word);
    };
  }
]);

function Shuffle(o) {
  for (var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
  return o;
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<div ng-app="ABCD">
  <div ng-controller="ABCDController">
    <button class="btn btn-primary" ng-click="shuffle()">Shuffle</button>
    <p>START WORD: {{start_word}}</p>
    <p ng-repeat="(key,value) in word">SHUFFLED WORD: {{value}}</p>
  </div>
</div>

share|improve this answer
    
This worked, but how slice() helped me here? I didnt get that part – ntechi Mar 2 '15 at 17:58
1  
@ntechi See edit. It's a way to copy an array. – camden_kid Mar 2 '15 at 18:01

You never reset your word array, so each new call to Shuffle() is adding onto the array instead of just replacing the contents of the array.

$scope.shuffle = function() {
  var shuffle_word = Shuffle($scope.word[0]);
  console.log("SHUFFLED VARIABLE: " + shuffle_word);
  console.log("SCOPE VARIABLE: " + $scope.word);
  $scope.word = []; //clear the previous array elements
  $scope.word.push(shuffle_word);
};

Or a a complete snippet (note I changed the word to "catalog").

var app = angular.module('ABCD', []);
app.controller('ABCDController', ['$scope',
  function($scope) {
    $scope.start_word = ['C', 'A', 'T', 'A', 'L', 'O', 'G'];
    $scope.word = [
      ['C', 'A', 'T', 'A', 'L', 'O', 'G']
    ];
    $scope.shuffle = function() {
      var shuffle_word = Shuffle($scope.word[0]);
      console.log("SHUFFLED VARIABLE: " + shuffle_word);
      console.log("SCOPE VARIABLE: " + $scope.word);
      $scope.word = []; //clear the previous array elements
      $scope.word.push(shuffle_word);
    };
  }
]);

function Shuffle(o) {
  for (var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
  return o;
}
  
<!DOCTYPE html>
<html ng-app="ABCD">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://code.angularjs.org/1.3.14/angular.js" data-semver="1.3.14"></script>
    <script src="app.js"></script>
  </head>

<div ng-app="ABCD">
  <div ng-controller="ABCDController">
    <button class="btn btn-primary" ng-click="shuffle()">Shuffle</button>
    <p>START WORD: {{start_word}}</p>
    <p ng-repeat="(key,value) in word ">SHUFFLED WORD: {{value}}</p>
  </div>
</div>

</html>

share|improve this answer

Perhaps try have a word object within the word array something like:

$scope.word[{num:0,word:'CAT'},{num:1,word:'ACT'}];
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.