如何将列表中的多字符串转为Map键?Scala实现单词-页码索引函数的数据格式化问询
Absolutely, you can reformat your data into the desired Map structure! Let's break down the approach step by step, then modify your code to implement it.
Understanding the Problem
Your current splitt variable is a List[(List[String], Int)]—each entry holds all words from a single line and the corresponding page number. We need to transform this into a Map[String, Set[Int]] where every word maps to the set of pages it appears on.
Core Approach
The key idea is to iterate over each entry in your list, then for every word in the entry's word list, update the map to include the current page number for that word. Here's how to do it:
- Start with an empty map (
Map.empty[String, Set[Int]]). - For each
(wordsList, page)tuple insplitt:- For each word in
wordsList, add the page number to the word's set in the map. If the word isn't already in the map, create a new entry with a singleton set containing the page.
- For each word in
Modified Code
Here's your updated function with the indexing logic added:
object G { def main(args: Array[String]): Unit = { val wordIndex = stwórzIndeks() // Print the index to verify results wordIndex.foreach { case (word, pages) => println(s"$word: ${pages.mkString(", ")}") } } def stwórzIndeks(): Map[String, Set[Int]] = { val linie = io.Source .fromResource("tekst.txt") .getLines .toList // Zip each line with its original index (starting at 0) val zippedLinie: List[(String, Int)] = linie.zipWithIndex // Convert each line to (list of words, page number) val splitt: List[(List[String], Int)] = zippedLinie.foldLeft(List.empty[(List[String], Int)]) { (acc, curr) => curr match { case (line, index) => val words = line.split("\\s+").toList // Note: Adjust page calculation if needed. Current logic reverses line order as pages. // Use index + 1 if you want first line to be page 1 instead. val page = zippedLinie.length - index (words, page) +: acc } } // Build the final word-to-page map splitt.foldLeft(Map.empty[String, Set[Int]]) { (acc, entry) => val (words, page) = entry words.foldLeft(acc) { (map, word) => // Update the map: add page to the word's set (create set if word is new) map.updated(word, map.getOrElse(word, Set.empty) + page) } } } }
Key Explanations
- Map Construction: The inner
foldLeftoverwordstakes the current map and updates each word's entry.map.getOrElse(word, Set.empty)retrieves the existing set of pages for the word (or an empty set if the word is new), then we add the current page to that set. - Page Number Adjustment: Your current code uses
zippedLinie.length - indexwhich treats the first line of the file as the last page. If you want the first line to correspond to page 1, change this calculation toindex + 1.
Optional Robustness Improvements
To make your index more accurate, consider adding word normalization:
- Convert all words to lowercase so "Hello" and "hello" are treated as the same key.
- Remove punctuation (e.g., commas, periods) from words. For example:
Useval cleanedWord = word.toLowerCase.replaceAll("[^a-zA-Z0-9]", "")cleanedWordinstead of the originalwordwhen updating the map to ensure consistent keying.
内容的提问来源于stack exchange,提问作者floppalover

