Advertisement
Guest User

Untitled

a guest
Sep 22nd, 2023
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 2.44 KB | None | 0 0
  1. use std::cmp::Reverse;
  2. use std::collections::BinaryHeap;
  3.  
  4. use rustc_hash::FxHashMap;
  5. use serde::{Deserialize, Serialize};
  6. use serde_json::from_str;
  7.  
  8. #[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
  9. struct Post {
  10.     _id: String,
  11.     title: String,
  12.     // #[serde(skip_serializing)]
  13.     tags: Vec<String>,
  14. }
  15.  
  16. #[derive(Debug, Serialize)]
  17. struct RelatedPosts<'a> {
  18.    _id: &'a str,
  19.     tags: &'a [String],
  20.    related: Vec<&'a Post>,
  21. }
  22.  
  23. fn main() {
  24.     let json_str = std::fs::read_to_string("../posts.json").unwrap();
  25.     let posts: Vec<Post> = from_str(&json_str).unwrap();
  26.  
  27.     let mut posts_by_tag = FxHashMap::default();
  28.     posts
  29.         .iter()
  30.         .enumerate()
  31.         .flat_map(|(idx, post)| std::iter::repeat(idx).zip(post.tags.iter().map(|x| x.as_str())))
  32.         .for_each(|(idx, tag)| {
  33.             posts_by_tag.entry(tag).or_insert(vec![]).push(idx);
  34.         });
  35.  
  36.     let mut related_posts = Vec::with_capacity(posts.len());
  37.     let mut tagged_post_count = vec![0; posts.len()];
  38.  
  39.     for (idx, post) in posts.iter().enumerate() {
  40.         tagged_post_count.fill(0);
  41.  
  42.         post.tags
  43.             .iter()
  44.             .map(|tag| posts_by_tag.get(tag.as_str()))
  45.             .flatten()
  46.             .flat_map(|x| x.iter())
  47.             .filter(|&&tagged_post| tagged_post != idx)
  48.             .for_each(|&tagged_post| {
  49.                 tagged_post_count[tagged_post] += 1;
  50.             });
  51.  
  52.         let mut top_five = BinaryHeap::new();
  53.         tagged_post_count
  54.             .iter()
  55.             .copied()
  56.             .enumerate()
  57.             .filter(|&(_, count)| count > 0)
  58.             .for_each(|(post, count)| {
  59.                 if top_five.len() < 5 {
  60.                     top_five.push((Reverse(count), post));
  61.                 } else {
  62.                     let (Reverse(cnt), _) = top_five.peek().unwrap();
  63.                     if count > *cnt {
  64.                         top_five.pop();
  65.                         top_five.push((Reverse(count), post));
  66.                     }
  67.                 }
  68.             });
  69.  
  70.         related_posts.push(RelatedPosts {
  71.             _id: &post._id,
  72.             tags: &post.tags,
  73.             related: top_five.into_iter().map(|(_, post)| &posts[post]).collect(),
  74.         });
  75.     }
  76.  
  77.     // Write the result to a JSON file.
  78.     let json_str = serde_json::to_string(&related_posts).unwrap();
  79.     std::fs::write("../related_posts_rust.json", json_str).unwrap();
  80. }
  81.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement