jakob
jakob

Reputation: 6005

How do I remove duplicate values from my Multidimensional array in a Scala way?

I'm trying extract some values from a String. The string contains several lines with values. The values on each line are number, firstname, last name. Then I want to filter by a given pattern and remove the duplicate numbers.

This is my test:

test("Numbers should be unique") {
    val s = Cool.prepareListAccordingToPattern(ALLOWED_PATTERN, "1234,örjan,nilsson\n4321,eva-lisa,nyman\n1234,eva,nilsson")
    assert(s.length == 2, "Well that didn't work.. ")
    info("Chopping seems to work. Filtered duplicate numbers. Expected 1234:4321, got: "+s(0)(0)+":"+s(1)(0))
  }

The methods:

def prepareListAccordingToPattern(allowedPattern: String, s: String) : Array[Array[String]] = {
    val lines = chop("\n", s)
    val choppedUp = lines.map(line =>
      chop(",", line)).filter(array =>
        array.length == 3 && array(0).matches(allowedPattern)
      )    
    choppedUp
}

def chop(splitSymbol: String, toChop: String) : Array[String] = {
    toChop.split(splitSymbol)
  }

My test fails as expected since I receive back a multidimensional array with duplicates:

[0]["1234","örjan","nilsson"]

[1]["4321","eva-lisa","nyman"]

[2]["1234","eva","nilsson"]

What I would like to do is to filter out the duplicated numbers, in this case "1234" so that I get back:

[0]["1234","örjan","nilsson"]

[1]["4321","eva-lisa","nyman"]

How should I do this in a scala way? Maybe I could attack this problem differently?

Upvotes: 0

Views: 720

Answers (2)

senia
senia

Reputation: 38045

val arr = Array(
  Array("1234","rjan","nilsson"),
  Array("4321","eva-lisa","nyman"),
  Array("1234","eva","nilsson")
)

arr.groupBy( _(0)).map{ case (_, vs) => vs.head}.toArray
// Array(Array(1234, rjan, nilsson), Array(4321, eva-lisa, nyman))

If you have a collection of elements (in this case Array of Array[String]) and want to get single element with every value of some property (in this case property is the first string from Array[String]) you should group elements of collection based on this property (arr.groupBy( _(0))) and then somehow select one element from every group. In this case we picked up the first element (Array[String]) from every group.

If you want to select any (not necessary first) element for every group you could convert every element (Array[String]) to the key-value pair ((String, Array[String])) where key is the value of target property, and then convert this collection of pairs to Map:

val myMap = arr.map{ a => a(0) -> a }.toMap
// Map(1234 -> Array(1234, eva, nilsson), 4321 -> Array(4321, eva-lisa, nyman))

myMap.values.toArray
// Array(Array(1234, eva, nilsson), Array(4321, eva-lisa, nyman))

In this case you'll get the last element from every group.

Upvotes: 1

om-nom-nom
om-nom-nom

Reputation: 62855

A bit implicit, but should work:

val arr = Array(
     Array("1234","rjan","nilsson"),
     Array("4321","eva-lisa","nyman"),
     Array("1234","eva","nilsson")
     )
arr.view.reverse.map(x => x.head -> x).toMap.values
// Iterable[Array[String]] = MapLike(Array(1234, rjan, nilsson), Array(4321, eva-lisa, nyman))

Reverse here to override "eva","nilsson" with "rjan","nilsson", not vice versa

Upvotes: 0

Related Questions