3

I apologize if my title sounds so confusing, as I don't know how to exactly word it. Basically, this is what I'm trying to do.

For example, I have the following array:

var sourceArray = [
     { question: "Question 1", inputType: "radio", answer: "Answer 1", id: "1" },
     { question: "Question 1", inputType: "radio", answer: "Answer 2", id: "2" },
     { question: "Question 1", inputType: "radio", answer: "Answer 3", id: "3" },
     { question: "Question 2", inputType: "radio", answer: "Answer 1", id: "4" },
     { question: "Question 2", inputType: "radio", answer: "Answer 2", id: "5" },
     { question: "Question 2", inputType: "radio", answer: "Answer 3", id: "6" }
]

I want to restructure this so that it'll look like this:

var newArray = [
     {
      question: "Question 1", inputType: "radio", 
      choices: [{answer: "Answer 1", id: "1"},
                {answer: "Answer 2", id: "2"},
                {answer: "Answer 3", id: "3"}
               ]},
     {
      question: "Question 2", inputType: "radio", 
      choices: [{answer: "Answer 1", id: "4"},
                {answer: "Answer 2", id: "5"},
                {answer: "Answer 3", id: "6"}
     ]}
]

Answers are grouped by question, so if the next question in the sourceArray is the same with the current, it will push the answers into the choices array.

Is this possible in AngularJS using angular.forEach?

Any help will be appreciated.

Thank you as always for your responses.

1
  • 3
    Could you post a plunker on how far you have accomplished to solve this? Commented Aug 1, 2016 at 6:09

3 Answers 3

3

Here you go. See the working example below:

// Add a hepler method in the Array to find the value
Array.prototype.find = function(key, value) {
  var index = -1;
  angular.forEach(this, function(item, i) {
    if (item[key] === value) {
      index = i;
    }
  });

  return this[index];
};

var app = angular.module("sa", []);

app.controller("FooController", function($scope) {

  $scope.sourceArray = [{
    question: "Question 1",
    inputType: "radio",
    answer: "Answer 1",
    id: "1"
  }, {
    question: "Question 1",
    inputType: "radio",
    answer: "Answer 2",
    id: "2"
  }, {
    question: "Question 1",
    inputType: "radio",
    answer: "Answer 3",
    id: "3"
  }, {
    question: "Question 2",
    inputType: "radio",
    answer: "Answer 1",
    id: "4"
  }, {
    question: "Question 2",
    inputType: "radio",
    answer: "Answer 2",
    id: "5"
  }, {
    question: "Question 2",
    inputType: "radio",
    answer: "Answer 3",
    id: "6"
  }];

  $scope.newArray = [];

  $scope.convert = function() {
    // Iterate array
    angular.forEach($scope.sourceArray, function(item) {
      // Check if the question alrady exists
      if (!$scope.newArray.find('question', item.question)) {
        // If not, push the question to the array with empty choices
        $scope.newArray.push({
          question: item.question,
          inputType: item.inputType,
          choices: []
        });
      }

      var newArrayItem = $scope.newArray.find('question', item.question);
      
      // Push the choices
      newArrayItem.choices.push({
        answer: item.answer,
        id: item.id
      });
    });
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">


<div ng-app="sa" ng-controller="FooController">
  Before:
  <br>{{sourceArray | json}}
  <br>
  <a href="" ng-click="convert()">convert</a>
  <br>After:
  <br>{{newArray | json}}
</div>

Sign up to request clarification or add additional context in comments.

3 Comments

Good approach. Liked.
You are a lifesaver, Shashank. This worked wonderfully. Thank you!
Glad this worked!! The main goal you understand the solution.
1

You can group together using a for loop,

Here is the code:

function transformArr(orig) {
    var newArr = [],
        answers = {},
        newItem, i, j, cur;
    for (i = 0, j = orig.length; i < j; i++) {
        cur = orig[i];
        if (!(cur.question in answers)) {
            answers[cur.question] = {question: cur.question, answers: [],inputType : cur.inputType,id :cur.id};
            newArr.push(answers[cur.question]);
        }
        answers[cur.question].answers.push(cur.answer);
    }
    return newArr;
}

Working App

Comments

0

You need to filter in the sourceArray, the two Questions List as below:

var question1 = $filter('filter')(sourceArray, {
  question: 'Question 1'
});
var question2 = $filter('filter')(sourceArray, {
  question: 'Question 2'
});

After that, you should create a new data of array as below:

$scope.questionData = [{
  "question": "Question 1",
  "inputType": "radio",
  "choices": []
}, {
  "question": "Question 2",
  "inputType": "radio",
  "choices": []
}];

Then, you should run loops over the two filtered a variables into the new Array of object:

1):

angular.forEach(question1, function(value, key) {
  if (value.question == $scope.questionData[0].question) {
    $scope.questionData[0].choices.push({
      'answer': value.answer,
      'id': value.id
    });
  }
});

2):

angular.forEach(question2, function(value, key) {
  if (value.question == $scope.questionData[1].question) {
    $scope.questionData[1].choices.push({
      'answer': value.answer,
      'id': value.id
    });
  }
});

Refer here for demo:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.