簡體   English   中英

在 C# 中表示評分矩陣的最佳方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM