কোনও সংগ্রহকে ম্যাপ-বাই-কীতে পরিণত করার সর্বোত্তম উপায়?


165

যদি আমি একটি সংগ্রহ আছে cধরনের Tএবং সেখানে একটি সম্পত্তি pউপর T(টাইপ এর Pবলো), একটি করতে সবচেয়ে ভালো উপায় কি মানচিত্র-বাই-আহরণের কী ?

val c: Collection[T]
val m: Map[P, T]

একটি উপায় নিম্নলিখিত:

m = new HashMap[P, T]
c foreach { t => m add (t.getP, t) }

তবে এখন আমার একটি পরিবর্তনীয় মানচিত্র দরকার । এটি করার আরও ভাল উপায় আছে যাতে এটি 1 লাইনে থাকে এবং আমি একটি অপরিবর্তনীয় মানচিত্রটি দিয়ে শেষ করি ? (অবশ্যই স্পষ্টভাবে আমি উপরেরটিকে একটি সাধারণ গ্রন্থাগার ইউটিলিটিতে পরিণত করতে পারি, যেমনটি আমি জাভাতে চাইতাম, তবে আমার সন্দেহ হয় যে স্কালায় কোনও প্রয়োজন নেই)

উত্তর:


232

তুমি ব্যবহার করতে পার

c map (t => t.getP -> t) toMap

তবে সচেতন থাকুন যে এর জন্য 2 ট্র্যাভারসাল দরকার।


8
আমি এখনও আমার ট্র্যাকগুলিতে আমার পরামর্শ পছন্দ করি Traversable[K].mapTo( K => V)এবং Traversable[V].mapBy( V => K)আরও ভাল ছিল!
অক্সবো_লাক্স 21

7
সচেতন থাকুন যে এটি চতুষ্কোণীয় ক্রিয়াকলাপ, তবে এখানে প্রদত্ত বেশিরভাগ বৈকল্পিকের ক্ষেত্রেও এটি একই রকম। সোপাল কোডোলকশন.মুটেবল.ম্যাপবিল্ডার ইত্যাদির উত্স কোডের দিকে তাকালে আমার কাছে মনে হয় যে প্রতিটি টিপল-এর ​​জন্য একটি নতুন অচল মানচিত্র তৈরি করা হয়েছে যেখানে এতে টুপল যুক্ত করা হয়েছে।
jcsahnwaldt মনিকা

30
500,000 উপাদান সহ একটি তালিকার জন্য আমার মেশিনে, এই স্কালা কোডটি সোজা-ফরোয়ার্ড জাভা পদ্ধতির চেয়ে 20 গুণ কম ধীরে ধীরে (উপযুক্ত আকারের সাথে হ্যাশম্যাপ তৈরি করুন, তালিকায় লুপ করুন, উপাদানগুলিকে মানচিত্রে রাখুন)। 5,000 টি উপাদানগুলির জন্য, স্কালা প্রায় 8 গুণ ধীর। স্কালায় লিখিত লুপ পদ্ধতির টোম্যাপ ভেরিয়েন্টের চেয়ে প্রায় 3 গুণ দ্রুত, তবে এখনও জাভা থেকে 2 থেকে 7 গুণ কম ধীর হয়।
জ্যাকসাহ্নওয়াল্ড্ট মনিকা

8
আপনি দয়া করে এসও সম্প্রদায়কে পরীক্ষার উত্স সরবরাহ করবেন? ধন্যবাদ.
ব্যবহারকারী573215

8
মধ্যবর্তী সংগ্রহ সৃষ্টি এড়াতে এর cসাথে প্রতিস্থাপন করুন c.iterator
ghik

21

আপনি পরিবর্তনশীল সংখ্যক টিউপস সহ একটি মানচিত্র তৈরি করতে পারেন। সুতরাং সংগ্রহে মানচিত্রের পদ্ধতিটি এটিকে টিপলসের সংকলনে রূপান্তর করতে ব্যবহার করুন এবং তারপরে ফলাফলটিকে ভেরিয়েবল আর্গুমেন্টে রূপান্তর করতে: _ * ট্রিক ব্যবহার করুন।

scala> val list = List("this", "maps", "string", "to", "length") map {s => (s, s.length)}
list: List[(java.lang.String, Int)] = List((this,4), (maps,4), (string,6), (to,2), (length,6))

scala> val list = List("this", "is", "a", "bunch", "of", "strings")
list: List[java.lang.String] = List(this, is, a, bunch, of, strings)

scala> val string2Length = Map(list map {s => (s, s.length)} : _*)
string2Length: scala.collection.immutable.Map[java.lang.String,Int] = Map(strings -> 7, of -> 2, bunch -> 5, a -> 1, is -> 2, this -> 4)

5
আমি 2 সপ্তাহ ধরে স্কালার সম্পর্কে পড়ছি এবং উদাহরণগুলির মাধ্যমে কাজ করছি এবং একবারও আমি এই ": _ *" স্বরলিপিটি দেখিনি! আপনার সহায়তার জন্য অনেক ধন্যবাদ
অক্সবো_লাক্স

কেবল রেকর্ডের জন্য, আমি অবাক হয়েছি কেন আমাদের ঠিক এটি দরকার যে এটি _ এর সাথে একটি ক্রম । মানচিত্র এখনও এখানে tuple একটি তালিকা ফিরে রূপান্তর। তাহলে কেন _ ? আমার অর্থ এটি কাজ করে তবে আমি এখানে
লেখার ধরণটি

1
এটি কি অন্যান্য পদ্ধতির তুলনায় আরও দক্ষ?
Jus12

16

@ জামেস আইরি এর সমাধান ছাড়াও, ভাঁজ ব্যবহার করে এটি সম্পন্ন করাও সম্ভব। আমার সন্দেহ হয় যে এই সমাধানটি টিউপল পদ্ধতির তুলনায় কিছুটা দ্রুত (কম জঞ্জাল সামগ্রী তৈরি করা হয়েছে):

val list = List("this", "maps", "string", "to", "length")
val map = list.foldLeft(Map[String, Int]()) { (m, s) => m(s) = s.length }

আমি এটি চেষ্টা করে দেখব (আমি নিশ্চিত এটি কাজ করে :-)। "(এম, এস) => মি (গুলি) = এস.লেন্থ" ফাংশন দিয়ে কী চলছে? আমি যোগফল এবং একটি ফাংশন "_ + _" সহ টিপিক্যাল ফোল্ড বাম উদাহরণটি দেখেছি; এটি আরও বিভ্রান্তিকর! ফাংশনটি ধরে নিয়েছে বলে মনে হচ্ছে যে আমার কাছে ইতিমধ্যে একটি টিউপল (মি, গুলি) রয়েছে যা আমি সত্যিই পাই না
অক্সবো_লাক

2
ম্যান, স্কালা তখন অদ্ভুত ছিল!
মিসিংফ্যাক্টর

8
@ ড্যানিয়েল আমি আপনার কোডটি চেষ্টা করে দেখি তবে নিম্নলিখিত ত্রুটিটি উপস্থিত হয়: "মান আপডেটটি স্কালাল কোডলিকেশন.নিমুটযোগ্য M মানচিত্রের সদস্য নয় ap মানচিত্র [স্ট্রিং, ইনট]"। এই কোডটি কীভাবে কাজ করবেন তা আপনার কোডটি ব্যাখ্যা করুন?
মিঃবয়ফক্স

1
আমার মনে হয় "অ্যাপ্লিকেশন প্যারামিটার নেয় না"
jayunit100

7
অপরিবর্তনীয় সংস্করণ: list.foldLeft(Map[String,Int]()) { (m,s) => m + (s -> s.length) }। নোট আপনি কমা ব্যবহার করতে tuple গড়ে তুলতে চান, আপনি প্রথম বন্ধনী একটি অতিরিক্ত যুগল প্রয়োজন যে: ((s, s.length))
কেলভিন

11

নিম্নলিখিত হিসাবে সংগ্রহের মাধ্যমে ভাঁজ করে এটি প্রতিরক্ষামূলকভাবে এবং একক ট্র্যাভারসাল সহ কার্যকর করা যেতে পারে।

val map = c.foldLeft(Map[P, T]()) { (m, t) => m + (t.getP -> t) }

সমাধানটি কাজ করে কারণ একটি অপরিবর্তনীয় মানচিত্র যুক্ত করা অতিরিক্ত প্রবেশের মাধ্যমে একটি নতুন প্রতিরক্ষামূলক মানচিত্র ফেরত দেয় এবং এই মানটি ভাঁজ অপারেশনের মাধ্যমে সঞ্চয়ের কাজ করে।

এখানে ট্রেড অফ হ'ল কোডটির দক্ষতা বনামের সরলতা। সুতরাং, বড় সংগ্রহের জন্য, 2 ট্র্যাভারসাল বাস্তবায়ন যেমন প্রয়োগ করা mapএবং ব্যবহারের চেয়ে এই পদ্ধতির আরও উপযুক্ত হতে পারে toMap


8

অন্য একটি সমাধান (সমস্ত ধরণের জন্য কাজ নাও করতে পারে)

import scala.collection.breakOut
val m:Map[P, T] = c.map(t => (t.getP, t))(breakOut)

এটি মধ্যস্থতাকারী তালিকা তৈরি করা এড়াতে পারে, আরও তথ্য এখানে: স্কেলা ২.৮ ব্রেকআউট


7

আপনি যা অর্জন করতে চাইছেন তা কিছুটা সংজ্ঞায়িত।
দুই বা ততোধিক আইটেম cএকই ভাগ হলে p? মানচিত্রে কোন আইটেমটি ম্যাপ করা হবে p?

এটি দেখার আরও সঠিক উপায়টি pএবং cএটিতে থাকা সমস্ত আইটেমের মধ্যে একটি মানচিত্র পাওয়া যাচ্ছে:

val m: Map[P, Collection[T]]

এটি গ্রুপবাইয়ের মাধ্যমে সহজেই অর্জন করা যেতে পারে :

val m: Map[P, Collection[T]] = c.groupBy(t => t.p)

আপনি যদি এখনও মূল মানচিত্র চান তবে উদাহরণস্বরূপ, এটিতে pপ্রথমটিতে ম্যাপ করতে tপারেন:

val m: Map[P, T] = c.groupBy(t => t.p) map { case (p, ts) =>  p -> ts.head }

1
এটির জন্য একটি সহজ টুইঙ্ক collectপরিবর্তে ব্যবহার করা হয় map। উদাহরণ: c.group(t => t.p) collect { case (Some(p), ts) => p -> ts.head }। যখন আপনি কী কী বিকল্প হয় তখন আপনি সমতল মানচিত্রের মতো কাজ করতে পারেন [_]।
healsjnr

@healsjnr অবশ্যই, এটি কোনও মানচিত্রের জন্যই বলা যেতে পারে। যদিও এটি এখানে মূল সমস্যা নয়।
ইয়াল রথ

1
আপনি .mapValues(_.head)মানচিত্রের পরিবর্তে ব্যবহার করতে পারেন ।
lex82

2

কোনও তালিকা মানচিত্রে ঘুরিয়ে দেওয়ার পক্ষে এটি সম্ভবত সবচেয়ে কার্যকর উপায় নয় তবে কলিং কোডটি আরও পঠনযোগ্য করে তোলে। আমি মানচিত্রে পদ্ধতিতে তালিকায় যুক্ত করতে অন্তর্ভুক্ত রূপান্তরগুলি ব্যবহার করেছি :

implicit def list2ListWithMapBy[T](list: List[T]): ListWithMapBy[T] = {
  new ListWithMapBy(list)
}

class ListWithMapBy[V](list: List[V]){
  def mapBy[K](keyFunc: V => K) = {
    list.map(a => keyFunc(a) -> a).toMap
  }
}

কলিং কোড উদাহরণ:

val list = List("A", "AA", "AAA")
list.mapBy(_.length)                  //Map(1 -> A, 2 -> AA, 3 -> AAA)

নোট করুন যে অন্তর্নিহিত রূপান্তরটির কারণে, কলার কোডকে স্কালার ইনপিকেটকভার্সনগুলি আমদানি করতে হবে।


2
c map (_.getP) zip c

ভাল কাজ করে এবং খুব স্বজ্ঞাত


8
আরও বিশদ যুক্ত করুন।
সৈয়দা জুনাইরা

2
আমি দুঃখিত. তবে, এটি কী "সংগ্রহকে মানচিত্র-বাই-কীতে রূপান্তরিত করার সবচেয়ে ভাল উপায়" প্রশ্নের উত্তর? বেন লিংস যেমন আছে
জার্গ বাচটিগার

1
এবং বেন কোন ব্যাখ্যা দেয়নি?
shinzou

1
এটি দুটি তালিকা তৈরি করে এবং cকী (সাজানো) হিসাবে উপাদানগুলি ব্যবহার করে একটি "মানচিত্র" এ একত্রিত করে । "মানচিত্র" দ্রষ্টব্য, কারণ ফলাফল সংগ্রহটি একটি স্কেল Mapনয় তবে আরও একটি তালিকা তৈরি করে / পুনরায় পুনরায় পুনরায় সাজানোর চেষ্টা করে ... তবে ওপির উদ্দেশ্যটির জন্য প্রভাবটি একই রকম আমি সরলতাকে ছাড় দেব না তবে এটি foldLeftসমাধানের মতো দক্ষ নয় , এটিও নয় "সংগ্রহকে একটি মানচিত্র-বাই-কীতে রূপান্তরিত করা" - এই প্রশ্নের আসল উত্তর
ডেক্সটার লেগাস্পি

2

জিপ এবং টু ম্যাপ ব্যবহার সম্পর্কে কীভাবে?

myList.zip(myList.map(_.length)).toMap

1

এটির জন্য মূল্যবান, এটি করার দুটি অর্থহীন উপায় এখানে :

scala> case class Foo(bar: Int)
defined class Foo

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> val c = Vector(Foo(9), Foo(11))
c: scala.collection.immutable.Vector[Foo] = Vector(Foo(9), Foo(11))

scala> c.map(((_: Foo).bar) &&& identity).toMap
res30: scala.collection.immutable.Map[Int,Foo] = Map(9 -> Foo(9), 11 -> Foo(11))

scala> c.map(((_: Foo).bar) >>= (Pair.apply[Int, Foo] _).curried).toMap
res31: scala.collection.immutable.Map[Int,Foo] = Map(9 -> Foo(9), 11 -> Foo(11))

এছাড়াও, নতুনভাবে, এই দু'জনকে হাস্কেলের মধ্যে এইভাবে দেখা হবে: Map.fromList $ map (bar &&& id) c, Map.fromList $ map (bar >>= (,)) c
মিসিংফ্যাক্টর

-1

এটি আমার পক্ষে কাজ করে:

val personsMap = persons.foldLeft(scala.collection.mutable.Map[Int, PersonDTO]()) {
    (m, p) => m(p.id) = p; m
}

মানচিত্রটি পরিবর্তনীয় হতে হবে এবং কোনও মানচিত্রের পরিবর্তে মানচিত্রটি ফেরত যেতে হবে যেহেতু একটি পরিবর্তনীয় মানচিত্রে যোগ করা কোনও মানচিত্র ফেরায় না।


1
প্রকৃতপক্ষে, এটি নিরপেক্ষভাবে প্রয়োগ করা যেতে পারে: val personsMap = persons.foldLeft(Map[Int, PersonDTO]()) { (m, p) => m + (p.id -> p) }উপরের প্রমাণ হিসাবে মানচিত্রটি পরিবর্তনযোগ্য হতে পারে, কারণ একটি অচল মানচিত্র যুক্ত করা অতিরিক্ত প্রবেশের সাথে একটি নতুন স্থাবর মানচিত্র ফিরিয়ে দেয়। এই মানটি ভাঁজ অপারেশনের মাধ্যমে সঞ্চয়ের কাজ করে।
রামভি

-2

টু ম্যাপের সাহায্যে সংগ্রহে মানচিত্র () ব্যবহার করুন

val map = list.map(e => (e, e.length)).toMap

3
7 বছর আগে জমা দেওয়া এবং স্বীকৃত উত্তর থেকে এটি কীভাবে আলাদা?
jwvh

-3

যদি জেসন স্ট্রিং (একটি জসন ফাইল পড়া) থেকে স্কেল ম্যাপে রূপান্তর করা হয়

import spray.json._
import DefaultJsonProtocol._

val jsonStr = Source.fromFile(jsonFilePath).mkString
val jsonDoc=jsonStr.parseJson
val map_doc=jsonDoc.convertTo[Map[String, JsValue]]

// Get a Map key value
val key_value=map_doc.get("key").get.convertTo[String]

// If nested json, re-map it.
val key_map=map_doc.get("nested_key").get.convertTo[Map[String, JsValue]]
println("Nested Value " + key_map.get("key").get)

এই 11 বছরের পুরানো প্রশ্নটি JSON সম্পর্কে কিছুই জিজ্ঞাসা করে না। আপনার উত্তর স্থানের বাইরে।
jwvh
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.