I've searched SO for a while trying to find an answer to this question as I imagine someone's run into this scenario. Please point me in the right direction if an answer is already out there. I have an array of objects containing books. These books are stored in a database and can have one or many writers. For each writer in the writers table, there is a column for book_id(FK), writer_name, and review_id(FK). Therefore if there are multiple writers on a book, there is a row for each writer containing the same information except the name. Here is an example of a JSON response from the DB:
var data = [
{"id": 1, "writer" : "John Joseph Doe", "review_id" : 4},
{"id": 1, "writer" : "Daniel Smith", "review_id" : 4},
{"id": 1, "writer" : "Thomas Edward Jones", "review_id" : 4},
{"id": 2, "writer" : "Erin Davis", "review_id" : 5},
{"id": 2, "writer" : "Jill Steinberg", "review_id" : 5},
{"id": 2, "writer" : "Laurie Beth Jennings", "review_id" : 5},
{"id": 3, "writer" : "Emma Jean Williams", "review_id" : 3},
{"id": 3, "writer" : "Mary Joe Williams", "review_id" : 3},
{"id": 3, "writer" : "Helen Andrews", "review_id" : 3},
{"id": 3, "writer" : "Samantha Jones", "review_id" : 3}
];
I would like to filter this array so that I end up with 3 objects, one for each book, that has no repeat values and each writer concatenated as a comma delimited string. Like so:
var data = [
{"id": 1, "writer" : "John Joseph Doe, Daniel Smith, Thomas Edward Jones", "review_id" : 4},
{"id": 2, "writer" : "Erin Davis, Jill Steinberg, Laurie Beth Jennings", "review_id" : 5},
{"id": 3, "writer" : "Emma Jean Williams, Mary Joe Williams, Helen Andrews, Samantha Jones", "review_id" : 3}
];
So I made an attempt to create a function that uses a for loop and a 'first' variable to keep track of which object I'm at based on it's id. My logic is to add each writer to the first instance of each object with a unique id, then remove all the proceeding objects with the same id after the writer has been added. Therefore I'm left with a single object for each book id and a concatenated string of writers separated by commas. The results are close to what I'm looking for, but I can't get it right. I'm not sure if removing the objects from the array is my issue or if I'm taking the entirely wrong approach in general. Here's a working fiddle: http://jsfiddle.net/mlabita37/Lvc0u55v/8987/ . There is a textarea above the table that I'm using as a 'console' to show the final data array, just expand to see the full result.
Here's some snippets of that code:
HTML:
<div ng-controller="BookCtrl">
<table class="table table-striped">
<thead>
<tr>
<th>Book ID</th>
<th>Writer</th>
<th>Review ID</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="book in books">
<td>{{ book.id }}</td>
<td>{{ book.writer }}</td>
<td>{{ book.review_id }}</td>
<textarea>{{ books }}</textarea>
</tr>
</tbody>
Controller:
var data = [
{"id": 1, "writer" : "John Joseph Doe", "review_id" : 4},
{"id": 1, "writer" : "Daniel Smith", "review_id" : 4},
{"id": 1, "writer" : "Thomas Edward Jones", "review_id" : 4},
{"id": 2, "writer" : "Erin Davis", "review_id" : 5},
{"id": 2, "writer" : "Jill Steinberg", "review_id" : 5},
{"id": 2, "writer" : "Laurie Beth Jennings", "review_id" : 5},
{"id": 3, "writer" : "Emma Jean Williams", "review_id" : 3},
{"id": 3, "writer" : "Mary Joe Williams", "review_id" : 3},
{"id": 3, "writer" : "Helen Andrews", "review_id" : 3},
{"id": 3, "writer" : "Samantha Jones", "review_id" : 3}
];
combine = function(data){
var first = data[0];
for(var i = 1; i < data.length; i++){
if(data[i].id === first.id){
first.writer = first.writer + ", " + data[i].writer;
data.splice(i, 1);
}
if(data[i].id !== first.id){
first = data[i];
var j = i+1;
if(data[j].id === first.id){
first.writer = first.writer + ", " + data[j].writer;
data.splice(j, 1);
}
}
}
};
combine(data);
$scope.books = data;
Another idea I had was to use a filter, however I don't have much experience with them and don't know if that would be a better approach. I also wasn't sure if this was something that could/should be handled in my MySQL query instead, or in the backend PHP. I'm under the impression that this is best handled on the front end.