0

I am having trouble "left joining" in Scala. For example,

val order: Array[Array[String]] = Array(Array("o2","ad1"), Array("o1","ad2"))

val line: Array[Array[String]] = Array(Array("l1","o1","x"),Array("l2","o2","y"))

Desired output:

Array(Array("l1","o1","x","ad2"),Array("l2","o2","y","ad1"))
2
  • How exactly are you having trouble left joining? What have you tried? Commented Feb 2, 2018 at 22:21
  • What is the desired result if there is no match for the "join" element, i.e. if order has no sub-array with the target string? Commented Feb 2, 2018 at 22:29

1 Answer 1

1

The modeling of the data is of questionable quality: why exactly do you want to represent everything as String arrays? But well, here you go:

    val order: Array[Array[String]] = Array(
  Array("o2","ad1"), 
  Array("o1","ad2"),
  Array("o7","ad5")
)
val line: Array[Array[String]] = Array(
  Array("l1","o1","x"),
  Array("l2","o2","y"),
  Array("l3","o13","z")
)

val orderAsMap = order.map{x => (x(0), x(1))}.toMap
val leftOuterJoin = for (x <- line) yield (x :+ orderAsMap.getOrElse(x(1), "<NULL>"))

// print to see the result
for (row <- leftOuterJoin) println(row.mkString(", "))

// output:
// 
// l1, o1, x, ad2
// l2, o2, y, ad1
// l3, o13, z, <NULL>

The intermediate toMap is necessary so that you don't have to traverse the entire array every time. The actual joining is done using the :+ operator.

Consider using an appropriate library if you have to deal with such questions regularly.

EDIT: Thanks @igorpcholkin for reminding me that "left join" is synonymous to "left OUTER join" in the usual nomenclature. The first version was rather something like an inner join. I'll leave it here just in case you want an inner join after all:

val order: Array[Array[String]] = Array(Array("o2","ad1"), Array("o1","ad2"))
val line: Array[Array[String]] = Array(
  Array("l1","o1","x"),
  Array("l2","o2","y"),
  Array("l3","o13","z")
)

val orderAsMap = order.map{x => (x(0), x(1))}.toMap
val lj = for {
  x <- line 
  if orderAsMap.contains(x(1))
} yield (x :+ orderAsMap(x(1)))

// print to see the result
for (row <- lj) println(row.mkString(", "))

// output:
// 
// l1, o1, x, ad2
// l2, o2, y, ad1
Sign up to request clarification or add additional context in comments.

9 Comments

@igorpcholkin Hm, no, it shouldn't. Have you seen the last update? I've added an if ... contains. It was missing in the first version, making it a very fragile left join.
@igorpcholkin How is it supposed to produced AIOOBE anyway, I never access arrays anywhere (except when extracting components from rows). But well, if the data is so broken that there are entries missing in some of the rows, then I don't know how to help...
Sorry my previous comment was incorrect. Actually the problem is that AIOOBE occurs in case of "ad?" (description?) missing for some order. The problem is in the line: "order.map{x => (x(0), x(1))}.toMap" which always assumes presence of at least two fields.
Another problem with your solution is that is doesn't actually produce "left join" but "inner join".
@igorpcholkin Yes, you are right again, thank you very much. "Left join" is of course "left outer join". I updated the answer. On missing "ad?"-column: I don't want to handle all the possible variants of how the data could be missing until the OP explicitly specifies that there actually can be missing values, and how those missing values are supposed to be represented.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.