Reputation: 9406
I have the following CSV:
Title, Rating, Year, Genre
All Quiet on the Western Front,8.1,1930,"Drama , War"
Gone with the Wind,8.2,1939,"Drama , Romance , War"
The Wizard of Oz,8.2,1939,"Adventure , Family , Fantasy , Musical"
Fantasia,7.9,1940,"Animation , Family , Fantasy , Music"
Pinocchio,7.6,1940,"Animation , Adventure , Drama , Family , Fantasy , Music"
The Great Dictator,8.5,1940,"Comedy , Drama , War"
Citizen Kane,8.5,1941,"Drama , Mystery"
Dumbo,7.3,1941,"Animation , Family , Musical"
Bambi,7.4,1942,"Animation , Drama , Family"
Casablanca,8.7,1942,"Drama , Romance , War"
It's a Wonderful Life,8.7,1946,"Drama , Family , Fantasy"
Notorious,8.2,1946,"Drama , Film-Noir , Romance , Thriller"
All About Eve,8.4,1950,Drama
Cinderella,7.3,1950,"Animation , Family , Fantasy , Musical , Romance"
Alice in Wonderland,7.4,1951,"Animation , Adventure , Family , Fantasy , Musical"
Strangers on a Train,8.2,1951,"Crime , Film-Noir , Thriller"
Dial M for Murder,8.2,1954,"Crime , Thriller"
Knock on Wood,7,1954,Comedy
Seven Samurai,8.8,1954,"Action , Drama"
Lady and the Tramp,7.4,1955,"Animation , Adventure , Comedy , Family , Romance"
Rebel Without a Cause,7.8,1955,"Drama , Romance"
The Trouble with Harry,7.2,1955,"Comedy , Mystery"
Forbidden Planet,7.7,1956,"Action , Adventure , Sci-Fi"
The Ten Commandments,7.9,1956,"Adventure , Drama , History"
12 Angry Men,8.9,1957,Drama
What I am trying to accomplish is this (My head is not working correctly right now):
Read the CSV and create an array that only shows all unique Genre (eg: Drama, War, Fantasy.. without repeating the Genre in the array)
Search the CSV for rows that have a specific Genre. For example, if I search for Drama, only rows that have the Drama value in the 4th column will be shown. (without showing the Genre column)
Sort the CSV by either Title, Rating or Year (without showing the Genre column).
I am reading the CSV in the following way:
$.ajax({
type: "GET",
url: "movies.csv",
dataType: "text",
success: function(data) {
var results = $.parse(data);
}
});
If I do a alert(JSON.stringify(results, null, 4))
it will print the correct information. The JSON Object looks like this:
{
"results": {
"fields": [
"Title",
" Rating",
" Year",
" Genre"
],
"rows": [
{
"Title": "All Quiet on the Western Front",
" Rating": 8.1,
" Year": 1930,
" Genre": "Drama , War"
},
{
"Title": "Gone with the Wind",
" Rating": 8.2,
" Year": 1939,
" Genre": "Drama , Romance , War"
},
{
"Title": "The Wizard of Oz",
" Rating": 8.2,
" Year": 1939,
" Genre": "Adventure , Family , Fantasy , Musical"
},
{
"Title": "Fantasia",
" Rating": 7.9,
" Year": 1940,
" Genre": "Animation , Family , Fantasy , Music"
So I know that part is working. I am trying to create an array and then fill a SELECT tag with the Genre values. Then if the user selects one of them, it will search the file again but only showing the rows that have the Genre specify. The user will be able to sort the list by the 3 first columns. My asking right now since my head (and eyesight) is not working very good right now.
Upvotes: 0
Views: 403
Reputation: 16659
The genre select
http://jsfiddle.net/coma/4N676/25/
var movies = new Movies(JSON.parse(gists.files.Movies.content));
var html = '<option>Filter by genre</option>';
movies.getGenres().forEach(function(genre) {
html += '<option value="' + genre + '">' + genre + '</option>';
});
$('#genre')
.html(html)
.change(function() {
var list = movies
.reset()
.filterByGenre(this.value)
.sortByTitleAsc()
.getList();
alert(JSON.stringify(list));
});
http://jsfiddle.net/coma/4N676/
Base
var Movies = function(movies)
{
var genres = [];
var ratingMin = Infinity;
var ratingMax = -1;
var yearMin = Infinity;
var yearMax = -1;
movies.forEach(function(movie, movieIndex) {
movie.Genre = movie.Genre.split(', ');
movie.Rating = parseFloat(movie.Rating);
movie.Year = parseInt(movie.Year, 10);
ratingMin = Math.min(movie.Rating, ratingMin);
ratingMax = Math.max(movie.Rating, ratingMax);
yearMin = Math.min(movie.Year, yearMin);
yearMax = Math.max(movie.Year, yearMax);
movie.Genre.forEach(function(genre, genreIndex) {
genre = $.trim(genre).toLowerCase();
movie.Genre[genreIndex] = genre;
if (genres.indexOf(genre) < 0) {
genres.push(genre);
}
genres.sort();
});
});
this.original = movies;
this.list = movies.slice();
this.ratingMin = ratingMin;
this.ratingMax = ratingMax;
this.yearMin = yearMin;
this.yearMax = yearMax;
this.genres = genres;
};
Movies.prototype.reset = function()
{
this.list = this.original.slice();
return this;
};
Getters
Movies.prototype.getList = function()
{
return this.list.slice();
};
Movies.prototype.getRatingRange = function()
{
return [this.ratingMin, this.ratingMax];
};
Movies.prototype.getRatingMax = function()
{
return this.ratingMax;
};
Movies.prototype.getRatingMin = function()
{
return this.ratingMin;
};
Movies.prototype.getYearRange = function()
{
return [this.yearMin, this.yearMax];
};
Movies.prototype.getYearMax = function()
{
return this.yearMax;
};
Movies.prototype.getYearMin = function()
{
return this.yearMin;
};
Movies.prototype.getGenres = function()
{
return this.genres.slice();
};
Filters
Movies.prototype.filterByNumbers = function(property, number)
{
if ($.isNumeric(number)) {
this.list = this.list.filter(function(movie) {
return movie[property] === number;
});
}
if ($.isArray(number)) {
this.list = this.list.filter(function(movie) {
return movie[property] >= number[0]
&& movie[property] <= number[1];
});
}
return this;
};
Movies.prototype.filterByGenre = function(genre)
{
this.list = this.list.filter(function(movie) {
return movie
.Genre
.indexOf(genre.toLowerCase()) >= 0;
});
return this;
};
Movies.prototype.filterByTitle = function(title)
{
this.list = this.list.filter(function(movie) {
return movie
.Title
.toLowerCase()
.indexOf(title.toLowerCase()) >= 0;
});
return this;
};
Movies.prototype.filterByYear = function(year)
{
this.filterByNumbers('Year', year);
return this;
};
Movies.prototype.filterByRating = function(rating)
{
this.filterByNumbers('Rating', rating);
return this;
};
Sorters
Movies.prototype.sortAsc = function(property)
{
this.list.sort(function(a, b) {
return a[property] > b[property];
});
return this;
};
Movies.prototype.sortDesc = function(property)
{
this.list.sort(function(a, b) {
return a[property] < b[property];
});
return this;
};
Movies.prototype.sortByTitleAsc = function()
{
this.sortAsc('Title');
return this;
};
Movies.prototype.sortByTitleDesc = function()
{
this.sortDesc('Title');
return this;
};
Movies.prototype.sortByYearAsc = function()
{
this.sortAsc('Year');
return this;
};
Movies.prototype.sortByYearDesc = function()
{
this.sortDesc('Year');
return this;
};
Movies.prototype.sortByRatingAsc = function()
{
this.sortAsc('Rating');
return this;
};
Movies.prototype.sortByRatingDesc = function()
{
this.sortDesc('Rating');
return this;
};
Usage
$.getJSON('https://api.github.com/gists/9803182', function(gists) {
var movies = new Movies(JSON.parse(gists.files.Movies.content));
movies
.filterByGenre('comedy')
.filterByYear([1954, 2000])
.sortByTitleDesc();
console.log('Filtered and sorted', movies.getList());
console.log('Original', movies.reset().getList());
});
Upvotes: 1
Reputation: 405
Ok, here it goes.
You can parse your JSON and traverse through it one by one. You would need to have a parent object which would keep your final rows vs. genre values.
The parent object would look something like this:
var myObject = {
genre : {records: []}
}
This will contain genre to records mapping.
While traversing the JSON object, if you find the genre already in your 'myObject', just push the record. If not, create the 'genre' and then push it.
Something like the below.
//Initialize my variables - Note, I'm using my own JSON
var objectArray = JSON.parse('[{"title":"title1","name":"name1","genre":"genre1"},{"title":"title2","name":"name2","genre":"genre2"},{"title":"title3","name":"name3","genre":"genre1"}]'),
counter=0,myObject={};
for (count=0; counter<objectArray.length; counter++) {
var individualRecord=objectArray[counter];
if(myObject[individualRecord.genre] === undefined) {
console.log('creating object');
myObject[individualRecord.genre]={records : []};
}
console.log('adding individual record');
myObject[individualRecord.genre].records.push(individualRecord);
}
console.log(myObject) will give you:
genre1 - Array with 2 elements
genre2 - Array with 1 element
Post this if you want to retrieve elements for a particular genre, you could just do this:
myObject["genre1"] - to handle dynamic genres
OR
myObject.genre1 - to explicitly fetch the value of the variable
Once you have the data stored in this format, you would not need to read the file again. You can filter based on myObject["<filter 1>"]
, etc..
Hope this helps!
Upvotes: 1