টিপলের তালিকায় মানচিত্রে রূপান্তর করুন (এবং ডুপ্লিকেট কী দিয়েছিলেন?)


92

আমি সদৃশ কী দ্বারা টুপলের একটি তালিকা [("a","b"),("c","d"),("a","f")]মানচিত্রে রূপান্তর করার একটি দুর্দান্ত উপায় সম্পর্কে ভাবছিলাম ("a" -> ["b", "f"], "c" -> ["d"])। সাধারণত (অজগরটিতে), আমি তালিকার উপরে একটি খালি মানচিত্র এবং ফর্ম লুপ তৈরি করে নকল কীটি পরীক্ষা করবো। তবে আমি এখানে আরও কিছু স্কেল-ইশ এবং চতুর সমাধানের সন্ধান করছি।

বিটিডব্লিউ, এখানে আমি যে ধরণের কী-মান ব্যবহার (Int, Node)করি তা হ'ল এবং আমি একটি মানচিত্রে রূপান্তর করতে চাই(Int -> NodeSeq)

উত্তর:


79

গ্রুপ এবং তারপরে প্রকল্প:

scala> val x = List("a" -> "b", "c" -> "d", "a" -> "f")
//x: List[(java.lang.String, java.lang.String)] = List((a,b), (c,d), (a,f))
scala> x.groupBy(_._1).map { case (k,v) => (k,v.map(_._2))}
//res1: scala.collection.immutable.Map[java.lang.String,List[java.lang.String]] = Map(c -> List(d), a -> List(b, f))

ভাঁজগুলি ব্যবহার করার মতো আরও স্কালিশ উপায়, সেখানকার মতো ( map fপদক্ষেপ এড়ান )।


125

এমন গুগলারের জন্য যা সদৃশদের প্রত্যাশা করে না বা ডিফল্ট সদৃশ হ্যান্ডলিং নীতিমালা দিয়ে ভাল রয়েছে :

List("a" -> 1, "b" -> 2).toMap
// Result: Map(a -> 1, c -> 2)

২.১২ হিসাবে, ডিফল্ট নীতিটি পড়ে:

সদৃশ কীগুলি পরবর্তী কীগুলির দ্বারা ওভাররাইট করা হবে: যদি এটি একটি আনর্ডারড সংগ্রহ হয় তবে ফলস্বরূপ মানচিত্রে কোন কীটি অপরিজ্ঞাত।


58

এখানে আরও একটি বিকল্প রয়েছে:

x.groupBy(_._1).mapValues(_.map(_._2))

এটি আমাদের একটি দেয় Map[String, SeqView[String,Seq[_]]]... এটি উদ্দেশ্যমূলক?
Luigi Plinge

4
@ লুইজিপ্লিনজ SeqView[String,Seq[_]]এও একটি Seq[String]। এখনও অনড় দৃষ্টিতে আমি তা সার্থক মনে করি না, তাই আমি এটি সরিয়েছি viewmapValuesমানগুলিতে যাই হোক না কেন একটি ভিউ করবে।
ড্যানিয়েল সি সোব্রাল

এটি আমার ক্ষেত্রে (কোর্স হোমওয়ার্ক) পুরোপুরিভাবে কাজটি করেছে: অলস ভ্যাল ডিকোরিয়ালটি বাইকসিওরেন্সস: মানচিত্র [ঘটনা, তালিকা [শব্দ]] = pairs ভাল জোড় = জন্য (কার্ফোর্ড <- অভিধান) ফলন cur ভল curWordOccurrences = শব্দঅ্যাক্সিয়েন্সস (curWord), কার্ফোর্ড)} જોડીઓ.groupBy ( ._1)। ম্যাপভ্যালু (। ম্যাপ (_._ 2))}
জেসনজি

মানচিত্রভ্যালুগুলি কোনও মানচিত্রের একটি দৃশ্য ফিরিয়ে দেয়, নতুন মানচিত্র নয়- স্কালা
ইন্ডেক্স। html#

4
সম্ভবত চান x.groupBy(_._1).mapValues(_.map(_._2)).map(identity)কারণ mapValuesপ্রতিবার এটি ব্যবহার করার সময় এক্সপ্রেশনটি পুনরায় সংশ্লেষ করা হবে। দেখুন issues.scala-lang.org/browse/SI-7005
জেফ্রি Aguilera

20

নকলগুলি সম্পর্কে যত্নশীল এমন গুগলারের জন্য:

implicit class Pairs[A, B](p: List[(A, B)]) {
  def toMultiMap: Map[A, List[B]] = p.groupBy(_._1).mapValues(_.map(_._2))
}

> List("a" -> "b", "a" -> "c", "d" -> "e").toMultiMap
> Map("a" -> List("b", "c"), "d" -> List("e")) 

12

শুরু করে Scala 2.13, বেশিরভাগ সংগ্রহগুলিতে গ্রুপম্যাপ পদ্ধতি সরবরাহ করা হয় যা এর নাম অনুসারে) এর সমতুল্য (আরও দক্ষ) groupByঅনুসরণ করা হয় mapValues:

List("a" -> "b", "c" -> "d", "a" -> "f").groupMap(_._1)(_._2)
// Map[String,List[String]] = Map(a -> List(b, f), c -> List(d))

এই:

  • groupটিপলসের প্রথম অংশের উপর ভিত্তি করে উপাদানসমূহ ( গ্রুপ মানচিত্রের গোষ্ঠী অংশ )

  • mapএর দ্বিতীয় দ্বিখণ্ডিত অংশ (গ্রুপ মানচিত্রের মানচিত্রের অংশ ) গ্রহণ করে গোষ্ঠীভুক্ত মানগুলি

এটি একটি সমতুল্য list.groupBy(_._1).mapValues(_.map(_._2))তবে তালিকার এক পাসে সঞ্চালিত


4

ডুপ্লিকেট কীগুলি পরিচালনা করে মানচিত্রের তালিকায় টিপলগুলির একটি তালিকা রূপান্তর করার জন্য এখানে আরও স্কাল আইডিয়োমেটিক উপায়। আপনি একটি ভাঁজ ব্যবহার করতে চান।

val x = List("a" -> "b", "c" -> "d", "a" -> "f")

x.foldLeft(Map.empty[String, Seq[String]]) { case (acc, (k, v)) =>
  acc.updated(k, acc.getOrElse(k, Seq.empty[String]) ++ Seq(v))
}

res0: scala.collection.immutable.Map[String,Seq[String]] = Map(a -> List(b, f), c -> List(d))

4
আপনি কেন মনে করেন এটি এখানে দেওয়া গ্রুপ-ম্যাপভ্যালু সলিউশনগুলির চেয়ে স্ক্যাল-স্টাইল বেশি?
Make42

@ ওম-নোম-নোম স্টেটমেন্ট "আরও ভালোভাবে ভাঁজ ব্যবহার করার উপায়, সেখানে (ম্যাপ এফ স্টেপ এড়িয়ে যাওয়া)" "
cevaris

আমি একটি যৌক্তিক যুক্তির জন্য আশা করি ;-)। ওম-নাম-মনোনীত বা লিঙ্কযুক্ত নিবন্ধটিই আমার প্রশ্নের প্রমাণ সরবরাহ করে না। (বা আমি এটি মিস করেছি?)
Make 42

4
@ মেক 42২ এটির মোকাবেলার আরও একটি সহজ উপায়, যেহেতু সমস্ত মনাদ মনোহাইড এবং আইন অনুসারে মনোয়েডগুলি ভাজযোগ্য। এফপি-তে, বস্তু এবং ইভেন্টগুলি মোনাড হিসাবে মডেল করা হয়, এবং সমস্ত মনাদ গোষ্ঠী দ্বারা প্রয়োগ করা হয় না।
soote

4

নীচে আপনি কয়েকটি সমাধান সন্ধান করতে পারেন। (গ্রুপ বাই, ফোল্ড লেফট, সমষ্টি, স্পার্ক)

val list: List[(String, String)] = List(("a","b"),("c","d"),("a","f"))

গ্রুপ-বাই প্রকরণ

list.groupBy(_._1).map(v => (v._1, v._2.map(_._2)))

বাম প্রকরণ ভাঁজ করুন

list.foldLeft[Map[String, List[String]]](Map())((acc, value) => {
  acc.get(value._1).fold(acc ++ Map(value._1 -> List(value._2))){ v =>
    acc ++ Map(value._1 -> (value._2 :: v))
  }
})

সমষ্টিগত পার্থক্য - বাম ভাঁজ করার অনুরূপ

list.aggregate[Map[String, List[String]]](Map())(
  (acc, value) => acc.get(value._1).fold(acc ++ Map(value._1 -> 
    List(value._2))){ v =>
     acc ++ Map(value._1 -> (value._2 :: v))
  },
  (l, r) => l ++ r
)

স্পার্কের তারতম্য - বড় ডেটা সেটগুলির জন্য (আরডিডি থেকে আরডিডি থেকে একটি সরল মানচিত্রে রূপান্তর)

import org.apache.spark.rdd._
import org.apache.spark.{SparkContext, SparkConf}

val conf: SparkConf = new 
SparkConf().setAppName("Spark").setMaster("local")
val sc: SparkContext = new SparkContext (conf)

// This gives you a rdd of the same result
val rdd: RDD[(String, List[String])] = sc.parallelize(list).combineByKey(
   (value: String) => List(value),
   (acc: List[String], value) => value :: acc,
   (accLeft: List[String], accRight: List[String]) => accLeft ::: accRight
)

// To convert this RDD back to a Map[(String, List[String])] you can do the following
rdd.collect().toMap

2

আপনি এটি চেষ্টা করতে পারেন

scala> val b = new Array[Int](3)
// b: Array[Int] = Array(0, 0, 0)
scala> val c = b.map(x => (x -> x * 2))
// c: Array[(Int, Int)] = Array((1,2), (2,4), (3,6))
scala> val d = Map(c : _*)
// d: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 2 -> 4, 3 -> 6)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.