[英]Best way to represent matrix of ratings in c#
我正在嘗試用 C# 構建一個推薦系統。 我想知道表示評分矩陣的最佳方式是什么。 每一行代表用戶,每一列代表一部電影。 例如,第 2 行第 4 列中的單元格將代表第 2 位用戶對第 4 部電影的評分(例如 1 到 5 星)。
值得一提的是,我需要對乘法轉置等數據進行一些矩陣代數。此外,矩陣將是稀疏的,因為當然並非所有用戶都對所有電影進行了評分。
這樣做的明顯方法是一個用戶名字符串數組、一個電影字符串數組和一個整數二維評級數組:
string[] users = new string[5] { "David", "Matt", "Ben", "Chris", "Torri" };
string[] movies = new string[4] { "Titanic", "X-men", "Snatch", "Speed"};
ratings = new int[5, 4];
問題是什么是最好的數據結構? 謝謝大家!
最好的方法是使用面向對象的編程方法:
// Note I'm going to use HashSet<T> everywhere because both movies and
// users should be unique in their respective collections
public class User
{
public sealed class UserEqualityComparer : IEqualityComparer<User>
{
public bool Equals(User a, User b)
{
return a != null && b != null && a.Name == b.Name;
}
public int GetHashCode(User some)
{
return some.Name.GetHashCode();
}
}
public string Name { get; set; }
// C# 6 expression bodied properties!!!!
public HashSet<Movie> LikesMovies { get; set; } = new HashSet<Movie>(new Movie.MovieEqualityComparer());
}
public class Movie
{
public sealed class MovieEqualityComparer : IEqualityComparer<Movie>
{
public bool Equals(Movie a, Movie b)
{
return a != null && b != null && a.Name == b.Name;
}
public int GetHashCode(Movie some)
{
return some.Name.GetHashCode();
}
}
public string Name { get; set; }
// C# 6 expression bodied properties!!!!
public HashSet<User> UsersWhoLikeIt { get; set; } = new HashSet<User>(new User.UserEqualityComparer());
}
現在,如果你想表示一個叫約翰的人喜歡星際迷航,你可以這樣做:
HashSet<Movie> movies = new HashSet<Movie>(new Movie.MovieEqualityComparer())
{
new Movie { Name = "Star Trek" },
new Movie { Name = "Star Wars" }
};
HashSet<User> users = new HashSet<User>(new User.UserEqualityComparer())
{
new User { Name = "John" },
new User { Name = "Jack" }
};
// Now an user likes a movie:
Movie movie = movies.Single(some => some.Name == "Star Trek");
User user = users.Single(some => some.Name == "John");
// You need to associate both sides of the whole M-N association:
// A movie can be liked by many users and an user can like many movies...
movie.UsersWhoLikeIt.Add(user);
user.LikesMovies.Add(movie);
用對象填充對象圖后,您只需要使用 LINQ 及其眾多擴展方法和自己的HashSet<T>
有趣的方法,如交集。
使用 OOP 有一個很大的優勢:您可以使用 OR/M 將該域映射到關系數據庫並存儲您的數據,或者您實際上可以將其直接存儲在 NoSQL 數據庫中。
請注意,我已經為您提供了一個實現likes的示例。 評級將由其他實體MovieRating表示,您可以在其中根據需要添加屬性來表示您的評級系統。
我不確定矩陣是最好的方法,但我也在這里假設您只是存儲評級。
我不確定最好的方法,但表示用戶電影評級的更好方法是分別對用戶、電影和評級進行建模。 稍后您可以選擇將值序列化到文件,或與數據庫接口,或您可以找到的任何其他數據持久性解決方案。
public class User
{
public string Name { get; set; }
}
public class Movie
{
public string Title { get; set; }
}
public class Rating
{
public User RatingUser { get; set; }
public Movie RatingMovie { get; set; }
}
接下來,將 User、Movie 和 Rating 模型動態添加到列表等簡單集合中。 您可以使用 LINQ 查詢這些集合。 此外,模型的縮放效果會更好(例如,將名稱重構為用戶的名字和姓氏,或為標題添加評級)。 這是使用列表的示例,並從您提供的代碼中添加用戶和電影值。
public List<User> UserList = new List<User>();
public List<Movie> MovieList = new List<Movie>();
public List<Ratings> RatingList = new List<Rating>();
UserList.Add(new User() { Name = "David"} );
UserList.Add(new User() { Name = "Matt"} );
UserList.Add(new User() { Name = "Ben"} );
UserList.Add(new User() { Name = "Chris"} );
UserList.Add(new User() { Name = "Torri"} );
MovieList.Add(new User() { Title = "Titanic"} );
MovieList.Add(new User() { Title = "X-men"} );
MovieList.Add(new User() { Title = "Snatch"} );
MovieList.Add(new User() { Title = "Speed"} );
如果您想做矩陣代數,那么就像您擁有它一樣,但您不需要 1-5 評級的 int
ratings = new byte[5, 4];
使用 0 表示未評級或字節? 並使用 null 表示未評級
您不能(輕松)調整數組大小
所以以非矩陣的方式將用戶、電影和用戶評分保存在數據庫中
然后,您將調整數組大小並從數據庫加載
ratingtable:
int userID PK
int movieID PK
byte rating
在表中,您不存儲 null 或 0 進行評分
如果它不存在,則不會對其進行評級
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.