# Modify \`r\`th largest entry of vector in place

**URL:** <https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587>\
**Category:** New to Julia\
**Tags:** scope\
**Created:** [February 19, 2021, 12:14am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587 "2021-02-19T00:14:16Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 12:14am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/1 "2021-02-19T00:14:16Z")

</div>

I can use `sortperm()` to get a permutation index that puts `a` in order:

```julia
3-element Array{Float64,1}:
 0.9546235783735173
 0.15267335513843228
 0.3175124947454555

julia> order = sortperm(a)
3-element Array{Int64,1}:
 2
 3
 1

julia> a[order]
3-element Array{Float64,1}:
 0.15267335513843228
 0.3175124947454555
 0.9546235783735173

```

I would like to do something like this to have the same effect as `a[1] = 1`, i.e. modify the largest entry of `a` in place.

```julia
julia> a[order][3] = 1
1

julia> a
3-element Array{Float64,1}:
 0.9546235783735173
 0.15267335513843228
 0.3175124947454555

```

Other than by making a copy of the sorted `a` and using `invperm()`, how can I accomplish this?

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 19, 2021, 12:19am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/2 "2021-02-19T00:19:11Z")

</div>

You would probably do `findfirst` for this. Something like

```julia
order = sortperm(a)
ind = findfirst(==(3), order)
a[ind] = 199

```

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 12:22am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/3 "2021-02-19T00:22:58Z")

</div>

This is equivalent to using `invperm()`–actually, slower, because with `invperm()` we can “find” all the `ind`s at the outset, which saves computation over many iterations.

I think the solution is `a[order[3]] = 1`, but I might just be getting lucky with permutation of periodicity 2.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 19, 2021, 12:24am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/4 "2021-02-19T00:24:41Z")

</div>

What do you mean? This avoids making a copy of the sorted `a`, which is what you wanted, correct?

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 12:29am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/5 "2021-02-19T00:29:53Z")

</div>

I am trying to cut down on both memory usage and computation cost.

Suppose `a` has n entries and we want to make k modifications. `sortperm()` costs n operations and each `findfirst()` (using linear search) costs another n, for a total cost of n + nk.

On the other hand, `invperm()` costs n operations and we only need to do it once, for a total cost of 2n + k.

On the other hand, if the code in the OP works, it should cost only n + k operations, if I am not mistaken.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 12:35am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/6 "2021-02-19T00:35:25Z")

</div>

To be clear, what I mean by the `invperm()` approach is

```julia
a_sorted = a[order]
a_sorted[3] = 1
a = a_sorted[invperm(order)]

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 19, 2021, 12:42am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/7 "2021-02-19T00:42:34Z")

</div>

Then why not just sort `a` and work with that?

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 12:50am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/8 "2021-02-19T00:50:11Z")

</div>

While we’re at it, why not sort _all_ vectors? The original order of `a` is meaningful.

For example, suppose `a` is a vector of scores on an exam, and the professor decides to bump up the bottom 10 scores to a 50%. The modified scores need to be associated with the names of the original students.

(This is a trivial example that could be coded easily with a list comprehension, but it illustrates the point.)

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 19, 2021, 12:55am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/9 "2021-02-19T00:55:41Z")

</div>

I’m confused. `sort(a)` returns a fresh vector, it doesn’t modify `a` at all. I’m proposing

```julia
a_sorted = sort(a)
third_highest = a_sorted[3]

```

A apologize for the confusion. I should have clarified that I was proposing making a copy. I’m not proposing `sort!`, which would modify in place.

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 1:05am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/10 "2021-02-19T01:05:11Z")

</div>

Thanks for slogging through it. After further experimentation, my previous idea of `a[order[3]] = 1` turns out to be correct.

The thing is, I _do_ want to modify `a`, in place, using a function whose behavior depends on which “rank” of `a` on which it operates.

```julia
julia> a = rand(10)
10-element Array{Float64,1}:
 0.9679461796327264
 0.06561999889746284
 0.11738337626095086
 0.7960588746091037
 0.8587013475046998
 0.10976984317050542
 0.24876025355689024
 0.8062624044798408
 0.2840384536852898
 0.8210625203870776

```

Suppose I want to replace the smallest entry with the number `1`, the second smallest with the number `64`, and the eighth smallest with its logarithm.

Notice that I can do this, _without copying_ `a` _or doing any searching other than the original sort,_ as follows:

```julia
julia> order = sortperm(a)
10-element Array{Int64,1}:
  2
  6
  3
  7
  9
  4
  8
 10
  5
  1

julia> a[order[1]] = 1
1

julia> a[order[2]] = 64
64

julia> a[order[8]] = log(a[order[8]])
-0.19715602092229395

julia> a
10-element Array{Float64,1}:
  0.9679461796327264
  1.0
  0.11738337626095086
  0.7960588746091037
  0.8587013475046998
 64.0
  0.24876025355689024
  0.8062624044798408
  0.2840384536852898
 -0.19715602092229395

```

And the unmodified entries of `a` still appear in the unmodified order.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 19, 2021, 1:10am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/11 "2021-02-19T01:10:52Z")

</div>

Yes. Remember that initially you wrote `a[order][3]`, which is very different than `a[order[3]]`

---

<div class="post-metadata">

**Author:** ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)\
**Post date:** [February 19, 2021, 1:13am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/12 "2021-02-19T01:13:41Z")

</div>

They don’t look very different from here!

```julia
julia> a = rand(100); order = sortperm(a);

julia> a[order[26]], a[order][26]
(0.2968121750980379, 0.2968121750980379)

```

This is why I have the [scope] tag on this post—I’m not sure why the first one enables me to target an entry of `a` for modification in a way that the second doesn’t.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [February 19, 2021, 1:16am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/13 "2021-02-19T01:16:15Z")

</div>

No, in terms of performance. `a[order][3]` first allocates the array `a[order]`. A whole vector the same size of `a`. `a[order[3]]` just does the `getindex`.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [February 19, 2021, 2:48am UTC](https://discourse.julialang.org/t/modify-r-th-largest-entry-of-vector-in-place/55587/14 "2021-02-19T02:48:27Z")

</div>

> [@maxkapur](#):
>
> I’m not sure why the first one enables me to target an entry of `a` for modification in a way that the second doesn’t.

The reason is the order of operations. The first one is equivalent to

```julia
i = order[26]
a[i] = 0 # a is modified

```

The second is equivalent to

```julia
b = a[order]
b[26] = 0 # a is not modified

```

Interestingly, you could make `b` from above be a view of `a` (unfortunately adding some overhead to each `setindex` operation, I should note)

```julia
order = sortperm(a)
b = @view a[order]
b[26] = 0 # a is also modified!

```
