# Apply function to one element only in list or array in Scala

For any given list or array like

``````val list = (1 to 3).toList
val array = (1 to 3).toArray
```

```

and a given function that maps from and to a collection type, for example

``````def f(v: Int): Int = v + 10
```

```

how to apply `f`

to the i-th element `list`

or `array`

to

``````list.myApply(f, ith = 2)
res: List(1,12,3)
```

```

and

``````array.myApply(f, ith = 2)
res: Array(1,12,3)
```

```
+3

source to share

TL; DR

``````import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom

implicit class Seq_[A, Repr,
S : ({type L[X] = X => SeqLike[A, Repr]})#L](seq: S) {

def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
```

```

Discussion

Naive approximation:

``````implicit class Seq_[A](seq: Seq[A]) {
def myApply(f: A => A, ith: Int): Seq[A] =
seq.updated(ith - 1, f(seq(ith - 1)))
}
```

```

Usage example:

``````scala> (1 to 3).toList.myApply(_ + 10, ith = 2)
res: Seq[Int] = List(1, 12, 3)
```

```

Attempted actual solution:

``````implicit class Seq_[A, Repr <: SeqLike[A, Repr]](seq: Repr) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
```

```

Unfortunately, implicit doesn't work. I'm not sure why.

``````scala> Seq_[Int, List[Int]]((1 to 3).toList).myApply(_ + 10, ith = 2)
res: List[Int] = List(1, 12, 3)

scala> Seq_[Int, List[Int]]((1 to 3).toList).myApply(_.toString + "*", ith = 2)
res: List[Any] = List(1, 2*, 3)
```

```

Edit: Fixed!

``````implicit class Seq_[A, Repr](seq: SeqLike[A, Repr]) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
```

```

Example:

``````scala> (1 to 3).toList.myApply(_ + 10, ith = 2)
res: List[Int] = List(1, 12, 3)

scala> (1 to 3).toVector.myApply(Math.pow(2, _), ith = 3)
res: scala.collection.immutable.Vector[AnyVal] = Vector(1, 2, 8.0)
```

```

But I just realized that you also wanted it to work for `Array`

, which it isn't `SeqLike`

, so let me think some more ...

Ah, `Predef`

has an implicit conversion from `Array`

to `ArrayOps`

, which is a subtype `SeqLike`

, so we just need to use an estimate.

``````implicit class Seq_[A, Repr <% SeqLike[A, Repr]](seq: Repr) {
def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
```

```

Finally, we have the correct behavior:

``````scala> (1 to 3).toList.myApply(_ + 10, ith = 2)
res: List[Int] = List(1, 12, 3)

scala> (1 to 3).toArray.myApply(Math.pow(2, _), ith = 3)
res: Array[AnyVal] = Array(1, 2, 8.0)
```

```

Edit again - samthebest informs me that view restrictions are deprecated, so using this guide we can replace it with a very ugly context related.

``````implicit class Seq_[A, Repr,
S : ({type L[X] = X => SeqLike[A, Repr]})#L](seq: S) {

def myApply[B >: A, That](f: A => B, ith: Int)
(implicit bf: CanBuildFrom[Repr, B, That]): That =
seq.updated(ith - 1, f(seq(ith - 1)))
}
```

```
+7

source

Someone just asked about the patch, so maybe this is a duplicate:

``````scala> val list = (1 to 3).toList
list: List[Int] = List(1, 2, 3)

scala> def f(v: Int): Int = v + 10
f: (v: Int)Int

scala> def g(is: Seq[Int], f: Int => Int, i: Int) = is.patch(i, Seq(f(is(i))), 1)
g: (is: Seq[Int], f: Int => Int, i: Int)Seq[Int]

scala> g(list, f, 1)
res1: Seq[Int] = List(1, 12, 3)
```

```

Summarizing smidgen:

``````scala> def g(is: collection.Seq[Int], f: Int => Int, i: Int, count: Int = 1) = is.patch(i, is.slice(i, i + count) map f, count)
g: (is: Seq[Int], f: Int => Int, i: Int, count: Int)Seq[Int]

scala> g(list, f, 1)
res2: Seq[Int] = List(1, 12, 3)

scala> g(list, f, 1, 2)
res3: Seq[Int] = List(1, 12, 13)
```

```

This was my first exit, as Chris suggests:

``````scala> def g(is: collection.mutable.Seq[Int], f: Int => Int, i: Int) = is(i) = f(is(i))
g: (is: scala.collection.mutable.Seq[Int], f: Int => Int, i: Int)Unit

scala> val as = (1 to 10).toArray
as: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> g(as, f, 1)

scala> as
res7: Array[Int] = Array(1, 12, 3, 4, 5, 6, 7, 8, 9, 10)
```

```

Since Chris said:

``````scala> def g(is: collection.Seq[Int], f: Int => Int, i: Int) = is.updated(i, f(is(i)))
g: (is: Seq[Int], f: Int => Int, i: Int)Seq[Int]
```

```

And good night, Gracie.

+3

source

It is very difficult to add additional methods to existing collections with implicits. If using external method OK, this is the solution. Almost there, but not quite. Example in Scala IDE worksheet

``````object SeqOps {
def applyToith(col: Seq[Int], f: Int => Int, ith: Int): Seq[Int] = {
val indexCol = col.zipWithIndex
indexCol.map {
a => if (a._2 == ith) f(a._1) else a._1
}
}                                       //> applyToith: (col: Seq[Int], f: Int => Int, ith: Int)Seq[Int]

def f(i: Int) = i + 10                  //> f: (i: Int)Int
val l = List(1, 2, 3)                   //> l  : List[Int] = List(1, 2, 3)
applyToith(l, f _, 0)                   //> res0: Seq[Int] = List(11, 2, 3)

val a = Array(1, 2, 3)                  //> a  : Array[Int] = Array(1, 2, 3)
applyToith(a, f _, 1)                   //> res1: Seq[Int] = ArrayBuffer(1, 12, 3)

val v = Vector(1, 2, 3)                 //> v  : scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
applyToith(v, f _, 2)                   //> res2: Seq[Int] = Vector(1, 2, 13)

}
```

```

In the case of an array, it returns ArrayBuffer instead of Array. For all other types, Seq works correctly. I've tried many other combinations but nothing fixes this problem.

``````val a : Seq[Int] = Array(1, 2)
a.zipWithIndex
```

```

This zipWithIndex returns an ArrayBuffer, but if used `val a: Array[Int]`

, it `zipWithIndex`

returns an Array.

Causal Java set bindings in the collections I think.

0

source

All Articles