Module docstring
{"## Operations using indexes ","### mapFinIdx ","### mapIdx "}
{"## Operations using indexes ","### mapFinIdx ","### mapIdx "}
List.mapFinIdx
definition
(as : List α) (f : (i : Nat) → α → (h : i < as.length) → β) : List β
/--
Applies a function to each element of the list along with the index at which that element is found,
returning the list of results. In addition to the index, the function is also provided with a proof
that the index is valid.
`List.mapIdx` is a variant that does not provide the function with evidence that the index is valid.
-/
@[inline] def mapFinIdx (as : List α) (f : (i : Nat) → α → (h : i < as.length) → β) : List β :=
go as #[] (by simp)
where
/-- Auxiliary for `mapFinIdx`:
`mapFinIdx.go [a₀, a₁, ...] acc = acc.toList ++ [f 0 a₀ ⋯, f 1 a₁ ⋯, ...]` -/
@[specialize] go : (bs : List α) → (acc : Array β) → bs.length + acc.size = as.length → List β
| [], acc, h => acc.toList
| a :: as, acc, h =>
go as (acc.push (f acc.size a (by simp at h; omega))) (by simp at h ⊢; omega)
List.mapIdx
definition
(f : Nat → α → β) (as : List α) : List β
/--
Applies a function to each element of the list along with the index at which that element is found,
returning the list of results.
`List.mapFinIdx` is a variant that additionally provides the function with a proof that the index
is valid.
-/
@[inline] def mapIdx (f : Nat → α → β) (as : List α) : List β := go as #[] where
/-- Auxiliary for `mapIdx`:
`mapIdx.go [a₀, a₁, ...] acc = acc.toList ++ [f acc.size a₀, f (acc.size + 1) a₁, ...]` -/
@[specialize] go : List α → Array β → List β
| [], acc => acc.toList
| a :: as, acc => go as (acc.push (f acc.size a))
List.mapFinIdxM
definition
[Monad m] (as : List α) (f : (i : Nat) → α → (h : i < as.length) → m β) : m (List β)
/--
Applies a monadic function to each element of the list along with the index at which that element is
found, returning the list of results. In addition to the index, the function is also provided with a
proof that the index is valid.
`List.mapIdxM` is a variant that does not provide the function with evidence that the index is
valid.
-/
@[inline] def mapFinIdxM [Monad m] (as : List α) (f : (i : Nat) → α → (h : i < as.length) → m β) : m (List β) :=
go as #[] (by simp)
where
/-- Auxiliary for `mapFinIdxM`:
`mapFinIdxM.go [a₀, a₁, ...] acc = acc.toList ++ [f 0 a₀ ⋯, f 1 a₁ ⋯, ...]` -/
@[specialize] go : (bs : List α) → (acc : Array β) → bs.length + acc.size = as.length → m (List β)
| [], acc, h => pure acc.toList
| a :: as, acc, h => do
go as (acc.push (← f acc.size a (by simp at h; omega))) (by simp at h ⊢; omega)
List.mapIdxM
definition
[Monad m] (f : Nat → α → m β) (as : List α) : m (List β)
/--
Applies a monadic function to each element of the list along with the index at which that element is
found, returning the list of results.
`List.mapFinIdxM` is a variant that additionally provides the function with a proof that the index
is valid.
-/
@[inline] def mapIdxM [Monad m] (f : Nat → α → m β) (as : List α) : m (List β) := go as #[] where
/-- Auxiliary for `mapIdxM`:
`mapIdxM.go [a₀, a₁, ...] acc = acc.toList ++ [f acc.size a₀, f (acc.size + 1) a₁, ...]` -/
@[specialize] go : List α → Array β → m (List β)
| [], acc => pure acc.toList
| a :: as, acc => do go as (acc.push (← f acc.size a))
List.mapFinIdx_congr
theorem
{xs ys : List α} (w : xs = ys) (f : (i : Nat) → α → (h : i < xs.length) → β) :
mapFinIdx xs f = mapFinIdx ys (fun i a h => f i a (by simp [w]; omega))
List.mapFinIdx_nil
theorem
{f : (i : Nat) → α → (h : i < 0) → β} : mapFinIdx [] f = []
List.length_mapFinIdx_go
theorem
: (mapFinIdx.go as f bs acc h).length = as.length
@[simp] theorem length_mapFinIdx_go :
(mapFinIdx.go as f bs acc h).length = as.length := by
induction bs generalizing acc with
| nil => simpa using h
| cons _ _ ih => simp [mapFinIdx.go, ih]
List.length_mapFinIdx
theorem
{as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} : (as.mapFinIdx f).length = as.length
@[simp] theorem length_mapFinIdx {as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} :
(as.mapFinIdx f).length = as.length := by
simp [mapFinIdx, length_mapFinIdx_go]
List.getElem_mapFinIdx_go
theorem
{as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} {i : Nat} {h} {w} :
(mapFinIdx.go as f bs acc h)[i] =
if w' : i < acc.size then acc[i] else f i (bs[i - acc.size]'(by simp at w; omega)) (by simp at w; omega)
theorem getElem_mapFinIdx_go {as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} {i : Nat} {h} {w} :
(mapFinIdx.go as f bs acc h)[i] =
if w' : i < acc.size then
acc[i]
else
f i (bs[i - acc.size]'(by simp at w; omega)) (by simp at w; omega) := by
induction bs generalizing acc with
| nil =>
simp only [length_mapFinIdx_go, length_nil, Nat.zero_add] at w h
simp only [mapFinIdx.go, Array.getElem_toList]
rw [dif_pos]
| cons _ _ ih =>
simp [mapFinIdx.go]
rw [ih]
simp
split <;> rename_i h₁ <;> split <;> rename_i h₂
· rw [Array.getElem_push_lt]
· have h₃ : i = acc.size := by omega
subst h₃
simp
· omega
· have h₃ : i - acc.size = (i - (acc.size + 1)) + 1 := by omega
simp [h₃]
List.getElem_mapFinIdx
theorem
{as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} {i : Nat} {h} :
(as.mapFinIdx f)[i] = f i (as[i]'(by simp at h; omega)) (by simp at h; omega)
@[simp] theorem getElem_mapFinIdx {as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} {i : Nat} {h} :
(as.mapFinIdx f)[i] = f i (as[i]'(by simp at h; omega)) (by simp at h; omega) := by
simp [mapFinIdx, getElem_mapFinIdx_go]
List.mapFinIdx_eq_ofFn
theorem
{as : List α} {f : (i : Nat) → α → (h : i < as.length) → β} :
as.mapFinIdx f = List.ofFn fun i : Fin as.length => f i as[i] i.2
List.getElem?_mapFinIdx
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {i : Nat} :
(l.mapFinIdx f)[i]? = l[i]?.pbind fun x m => f i x (by simp [getElem?_eq_some_iff] at m; exact m.1)
@[simp] theorem getElem?_mapFinIdx {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {i : Nat} :
(l.mapFinIdx f)[i]? = l[i]?.pbind fun x m => f i x (by simp [getElem?_eq_some_iff] at m; exact m.1) := by
simp only [getElem?_def, length_mapFinIdx, getElem_mapFinIdx]
split <;> simp
List.mapFinIdx_cons
theorem
{l : List α} {a : α} {f : (i : Nat) → α → (h : i < l.length + 1) → β} :
mapFinIdx (a :: l) f = f 0 a (by omega) :: mapFinIdx l (fun i a h => f (i + 1) a (by omega))
@[simp]
theorem mapFinIdx_cons {l : List α} {a : α} {f : (i : Nat) → α → (h : i < l.length + 1) → β} :
mapFinIdx (a :: l) f = f 0 a (by omega) :: mapFinIdx l (fun i a h => f (i + 1) a (by omega)) := by
apply ext_getElem
· simp
· rintro (_|i) h₁ h₂ <;> simp
List.mapFinIdx_append
theorem
{xs ys : List α} {f : (i : Nat) → α → (h : i < (xs ++ ys).length) → β} :
(xs ++ ys).mapFinIdx f =
xs.mapFinIdx (fun i a h => f i a (by simp; omega)) ++
ys.mapFinIdx (fun i a h => f (i + xs.length) a (by simp; omega))
theorem mapFinIdx_append {xs ys : List α} {f : (i : Nat) → α → (h : i < (xs ++ ys).length) → β} :
(xs ++ ys).mapFinIdx f =
xs.mapFinIdx (fun i a h => f i a (by simp; omega)) ++
ys.mapFinIdx (fun i a h => f (i + xs.length) a (by simp; omega)) := by
apply ext_getElem
· simp
· intro i h₁ h₂
rw [getElem_append]
simp only [getElem_mapFinIdx, length_mapFinIdx]
split <;> rename_i h
· rw [getElem_append_left]
· simp only [Nat.not_lt] at h
rw [getElem_append_right h]
congr
omega
List.mapFinIdx_concat
theorem
{l : List α} {e : α} {f : (i : Nat) → α → (h : i < (l ++ [e]).length) → β} :
(l ++ [e]).mapFinIdx f = l.mapFinIdx (fun i a h => f i a (by simp; omega)) ++ [f l.length e (by simp)]
@[simp] theorem mapFinIdx_concat {l : List α} {e : α} {f : (i : Nat) → α → (h : i < (l ++ [e]).length) → β}:
(l ++ [e]).mapFinIdx f = l.mapFinIdx (fun i a h => f i a (by simp; omega)) ++ [f l.length e (by simp)] := by
simp [mapFinIdx_append]
List.mapFinIdx_singleton
theorem
{a : α} {f : (i : Nat) → α → (h : i < 1) → β} : [a].mapFinIdx f = [f 0 a (by simp)]
theorem mapFinIdx_singleton {a : α} {f : (i : Nat) → α → (h : i < 1) → β} :
[a].mapFinIdx f = [f 0 a (by simp)] := by
simp
List.mapFinIdx_eq_zipIdx_map
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f =
l.zipIdx.attach.map fun ⟨⟨x, i⟩, m⟩ =>
f i x (by rw [mk_mem_zipIdx_iff_getElem?, getElem?_eq_some_iff] at m; exact m.1)
theorem mapFinIdx_eq_zipIdx_map {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l.zipIdx.attach.map
fun ⟨⟨x, i⟩, m⟩ =>
f i x (by rw [mk_mem_zipIdx_iff_getElem?, getElem?_eq_some_iff] at m; exact m.1) := by
apply ext_getElem <;> simp
List.mapFinIdx_eq_zipWithIndex_map
abbrev
@[deprecated mapFinIdx_eq_zipIdx_map (since := "2025-01-21")]
abbrev mapFinIdx_eq_zipWithIndex_map := @mapFinIdx_eq_zipIdx_map
List.mapFinIdx_eq_nil_iff
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} : l.mapFinIdx f = [] ↔ l = []
@[simp]
theorem mapFinIdx_eq_nil_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = [] ↔ l = [] := by
rw [mapFinIdx_eq_zipIdx_map, map_eq_nil_iff, attach_eq_nil_iff, zipIdx_eq_nil_iff]
List.mapFinIdx_ne_nil_iff
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} : l.mapFinIdx f ≠ [] ↔ l ≠ []
theorem mapFinIdx_ne_nil_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f ≠ []l.mapFinIdx f ≠ [] ↔ l ≠ [] := by
simp
List.exists_of_mem_mapFinIdx
theorem
{b : β} {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} (h : b ∈ l.mapFinIdx f) :
∃ (i : Nat) (h : i < l.length), f i l[i] h = b
theorem exists_of_mem_mapFinIdx {b : β} {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β}
(h : b ∈ l.mapFinIdx f) : ∃ (i : Nat) (h : i < l.length), f i l[i] h = b := by
rw [mapFinIdx_eq_zipIdx_map] at h
replace h := exists_of_mem_map h
simp only [mem_attach, true_and, Subtype.exists, Prod.exists, mk_mem_zipIdx_iff_getElem?] at h
obtain ⟨b, i, h, rfl⟩ := h
rw [getElem?_eq_some_iff] at h
obtain ⟨h', rfl⟩ := h
exact ⟨i, h', rfl⟩
List.mem_mapFinIdx
theorem
{b : β} {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
b ∈ l.mapFinIdx f ↔ ∃ (i : Nat) (h : i < l.length), f i l[i] h = b
@[simp] theorem mem_mapFinIdx {b : β} {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
b ∈ l.mapFinIdx fb ∈ l.mapFinIdx f ↔ ∃ (i : Nat) (h : i < l.length), f i l[i] h = b := by
constructor
· intro h
exact exists_of_mem_mapFinIdx h
· rintro ⟨i, h, rfl⟩
rw [mem_iff_getElem]
exact ⟨i, by simpa using h, by simp⟩
List.mapFinIdx_eq_cons_iff
theorem
{l : List α} {b : β} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = b :: l₂ ↔
∃ (a : α) (l₁ : List α) (w : l = a :: l₁),
f 0 a (by simp [w]) = b ∧ l₁.mapFinIdx (fun i a h => f (i + 1) a (by simp [w]; omega)) = l₂
theorem mapFinIdx_eq_cons_iff {l : List α} {b : β} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = b :: l₂ ↔
∃ (a : α) (l₁ : List α) (w : l = a :: l₁),
f 0 a (by simp [w]) = b ∧ l₁.mapFinIdx (fun i a h => f (i + 1) a (by simp [w]; omega)) = l₂ := by
cases l with
| nil => simp
| cons x l' =>
simp only [mapFinIdx_cons, cons.injEq, length_cons, Fin.zero_eta, Fin.cast_succ_eq,
exists_and_left]
constructor
· rintro ⟨rfl, rfl⟩
refine ⟨x, l', ⟨rfl, rfl⟩, by simp⟩
· rintro ⟨a, l', ⟨rfl, rfl⟩, ⟨rfl, rfl⟩⟩
exact ⟨rfl, by simp⟩
List.mapFinIdx_eq_cons_iff'
theorem
{l : List α} {b : β} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = b :: l₂ ↔
l.head?.pbind (fun x m => (f 0 x (by cases l <;> simp_all))) = some b ∧
l.tail?.attach.map (fun ⟨t, m⟩ => t.mapFinIdx fun i a h => f (i + 1) a (by cases l <;> simp_all)) = some l₂
theorem mapFinIdx_eq_cons_iff' {l : List α} {b : β} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = b :: l₂ ↔
l.head?.pbind (fun x m => (f 0 x (by cases l <;> simp_all))) = some b ∧
l.tail?.attach.map (fun ⟨t, m⟩ => t.mapFinIdx fun i a h => f (i + 1) a (by cases l <;> simp_all)) = some l₂ := by
cases l <;> simp
List.mapFinIdx_eq_iff
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l' ↔ ∃ h : l'.length = l.length, ∀ (i : Nat) (h : i < l.length), l'[i] = f i l[i] h
theorem mapFinIdx_eq_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l' ↔ ∃ h : l'.length = l.length, ∀ (i : Nat) (h : i < l.length), l'[i] = f i l[i] h := by
constructor
· rintro rfl
simp
· rintro ⟨h, w⟩
apply ext_getElem <;> simp_all
List.mapFinIdx_eq_singleton_iff
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {b : β} :
l.mapFinIdx f = [b] ↔ ∃ (a : α) (w : l = [a]), f 0 a (by simp [w]) = b
@[simp] theorem mapFinIdx_eq_singleton_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {b : β} :
l.mapFinIdx f = [b] ↔ ∃ (a : α) (w : l = [a]), f 0 a (by simp [w]) = b := by
simp [mapFinIdx_eq_cons_iff]
List.mapFinIdx_eq_append_iff
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l₁ ++ l₂ ↔
∃ (l₁' : List α) (l₂' : List α) (w : l = l₁' ++ l₂'),
l₁'.mapFinIdx (fun i a h => f i a (by simp [w]; omega)) = l₁ ∧
l₂'.mapFinIdx (fun i a h => f (i + l₁'.length) a (by simp [w]; omega)) = l₂
theorem mapFinIdx_eq_append_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l₁ ++ l₂ ↔
∃ (l₁' : List α) (l₂' : List α) (w : l = l₁' ++ l₂'),
l₁'.mapFinIdx (fun i a h => f i a (by simp [w]; omega)) = l₁ ∧
l₂'.mapFinIdx (fun i a h => f (i + l₁'.length) a (by simp [w]; omega)) = l₂ := by
rw [mapFinIdx_eq_iff]
constructor
· intro ⟨h, w⟩
simp only [length_append] at h
refine ⟨l.take l₁.length, l.drop l₁.length, by simp, ?_⟩
constructor
· apply ext_getElem
· simp
omega
· intro i hi₁ hi₂
simp only [getElem_mapFinIdx, getElem_take]
specialize w i (by omega)
rw [getElem_append_left hi₂] at w
exact w.symm
· apply ext_getElem
· simp
omega
· intro i hi₁ hi₂
simp only [getElem_mapFinIdx, getElem_take]
simp only [length_take, getElem_drop]
have : l₁.length ≤ l.length := by omega
simp only [Nat.min_eq_left this, Nat.add_comm]
specialize w (i + l₁.length) (by omega)
rw [getElem_append_right (by omega)] at w
simpa using w.symm
· rintro ⟨l₁', l₂', rfl, rfl, rfl⟩
refine ⟨by simp, fun i h => ?_⟩
rw [getElem_append]
split <;> rename_i h'
· simp [getElem_append_left (by simpa using h')]
· simp only [length_mapFinIdx, Nat.not_lt] at h'
have : i - l₁'.length + l₁'.length = i := by omega
simp [getElem_append_right h', this]
List.mapFinIdx_eq_mapFinIdx_iff
theorem
{l : List α} {f g : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l.mapFinIdx g ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] h = g i l[i] h
theorem mapFinIdx_eq_mapFinIdx_iff {l : List α} {f g : (i : Nat) → α → (h : i < l.length) → β} :
l.mapFinIdx f = l.mapFinIdx g ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] h = g i l[i] h := by
rw [eq_comm, mapFinIdx_eq_iff]
simp [Fin.forall_iff]
List.mapFinIdx_mapFinIdx
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {g : (i : Nat) → β → (h : i < (l.mapFinIdx f).length) → γ} :
(l.mapFinIdx f).mapFinIdx g = l.mapFinIdx (fun i a h => g i (f i a h) (by simpa))
List.mapFinIdx_eq_replicate_iff
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {b : β} :
l.mapFinIdx f = replicate l.length b ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] h = b
theorem mapFinIdx_eq_replicate_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {b : β} :
l.mapFinIdx f = replicate l.length b ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] h = b := by
rw [eq_replicate_iff, length_mapFinIdx]
simp only [mem_mapFinIdx, forall_exists_index, true_and]
constructor
· intro w i h
exact w (f i l[i] h) i h rfl
· rintro w b i h rfl
exact w i h
List.mapFinIdx_reverse
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.reverse.length) → β} :
l.reverse.mapFinIdx f = (l.mapFinIdx (fun i a h => f (l.length - 1 - i) a (by simp; omega))).reverse
List.mapIdx_nil
theorem
{f : Nat → α → β} : mapIdx f [] = []
List.mapIdx_go_length
theorem
{acc : Array β} : length (mapIdx.go f l acc) = length l + acc.size
theorem mapIdx_go_length {acc : Array β} :
length (mapIdx.go f l acc) = length l + acc.size := by
induction l generalizing acc with
| nil => simp only [mapIdx.go, length_nil, Nat.zero_add]
| cons _ _ ih =>
simp only [mapIdx.go, ih, Array.size_push, Nat.add_succ, length_cons, Nat.add_comm]
List.length_mapIdx_go
theorem
: ∀ {l : List α} {acc : Array β}, (mapIdx.go f l acc).length = l.length + acc.size
List.length_mapIdx
theorem
{l : List α} : (l.mapIdx f).length = l.length
@[simp] theorem length_mapIdx {l : List α} : (l.mapIdx f).length = l.length := by
simp [mapIdx, length_mapIdx_go]
List.getElem?_mapIdx_go
theorem
:
∀ {l : List α} {acc : Array β} {i : Nat},
(mapIdx.go f l acc)[i]? = if h : i < acc.size then some acc[i] else Option.map (f i) l[i - acc.size]?
theorem getElem?_mapIdx_go : ∀ {l : List α} {acc : Array β} {i : Nat},
(mapIdx.go f l acc)[i]? =
if h : i < acc.size then some acc[i] else Option.map (f i) l[i - acc.size]?
| [], acc, i => by
simp only [mapIdx.go, Array.toListImpl_eq, getElem?_def, Array.length_toList,
← Array.getElem_toList, length_nil, Nat.not_lt_zero, ↓reduceDIte, Option.map_none']
| a :: l, acc, i => by
rw [mapIdx.go, getElem?_mapIdx_go]
simp only [Array.size_push]
split <;> split
· simp only [Option.some.injEq]
rw [← Array.getElem_toList]
simp only [Array.push_toList]
rw [getElem_append_left, ← Array.getElem_toList]
· have : i = acc.size := by omega
simp_all
· omega
· have : i - acc.size = i - (acc.size + 1) + 1 := by omega
simp_all
List.getElem?_mapIdx
theorem
{l : List α} {i : Nat} : (l.mapIdx f)[i]? = Option.map (f i) l[i]?
@[simp] theorem getElem?_mapIdx {l : List α} {i : Nat} :
(l.mapIdx f)[i]? = Option.map (f i) l[i]? := by
simp [mapIdx, getElem?_mapIdx_go]
List.getElem_mapIdx
theorem
{l : List α} {f : Nat → α → β} {i : Nat} {h : i < (l.mapIdx f).length} :
(l.mapIdx f)[i] = f i (l[i]'(by simpa using h))
@[simp] theorem getElem_mapIdx {l : List α} {f : Nat → α → β} {i : Nat} {h : i < (l.mapIdx f).length} :
(l.mapIdx f)[i] = f i (l[i]'(by simpa using h)) := by
apply Option.some_inj.mp
rw [← getElem?_eq_getElem, getElem?_mapIdx, getElem?_eq_getElem (by simpa using h)]
simp
List.mapFinIdx_eq_mapIdx
theorem
{l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {g : Nat → α → β}
(h : ∀ (i : Nat) (h : i < l.length), f i l[i] h = g i l[i]) : l.mapFinIdx f = l.mapIdx g
List.mapIdx_eq_mapFinIdx
theorem
{l : List α} {f : Nat → α → β} : l.mapIdx f = l.mapFinIdx (fun i a _ => f i a)
theorem mapIdx_eq_mapFinIdx {l : List α} {f : Nat → α → β} :
l.mapIdx f = l.mapFinIdx (fun i a _ => f i a) := by
simp [mapFinIdx_eq_mapIdx]
List.mapIdx_eq_zipIdx_map
theorem
{l : List α} {f : Nat → α → β} : l.mapIdx f = l.zipIdx.map (fun ⟨a, i⟩ => f i a)
theorem mapIdx_eq_zipIdx_map {l : List α} {f : Nat → α → β} :
l.mapIdx f = l.zipIdx.map (fun ⟨a, i⟩ => f i a) := by
ext1 i
simp only [getElem?_mapIdx, Option.map, getElem?_map, getElem?_zipIdx]
split <;> simp
List.mapIdx_eq_enum_map
abbrev
@[deprecated mapIdx_eq_zipIdx_map (since := "2025-01-21")]
abbrev mapIdx_eq_enum_map := @mapIdx_eq_zipIdx_map
List.mapIdx_cons
theorem
{l : List α} {a : α} : mapIdx f (a :: l) = f 0 a :: mapIdx (fun i => f (i + 1)) l
@[simp]
theorem mapIdx_cons {l : List α} {a : α} :
mapIdx f (a :: l) = f 0 a :: mapIdx (fun i => f (i + 1)) l := by
simp [mapIdx_eq_zipIdx_map, List.zipIdx_succ]
List.mapIdx_append
theorem
{xs ys : List α} : (xs ++ ys).mapIdx f = xs.mapIdx f ++ ys.mapIdx fun i => f (i + xs.length)
theorem mapIdx_append {xs ys : List α} :
(xs ++ ys).mapIdx f = xs.mapIdx f ++ ys.mapIdx fun i => f (i + xs.length) := by
induction xs generalizing f with
| nil => rfl
| cons _ _ ih => simp [ih (f := fun i => f (i + 1)), Nat.add_assoc]
List.mapIdx_concat
theorem
{l : List α} {e : α} : mapIdx f (l ++ [e]) = mapIdx f l ++ [f l.length e]
@[simp] theorem mapIdx_concat {l : List α} {e : α} :
mapIdx f (l ++ [e]) = mapIdx f l ++ [f l.length e] := by
simp [mapIdx_append]
List.mapIdx_singleton
theorem
{a : α} : mapIdx f [a] = [f 0 a]
theorem mapIdx_singleton {a : α} : mapIdx f [a] = [f 0 a] := by
simp
List.mapIdx_eq_nil_iff
theorem
{l : List α} : List.mapIdx f l = [] ↔ l = []
@[simp]
theorem mapIdx_eq_nil_iff {l : List α} : List.mapIdxList.mapIdx f l = [] ↔ l = [] := by
rw [List.mapIdx_eq_zipIdx_map, List.map_eq_nil_iff, List.zipIdx_eq_nil_iff]
List.mapIdx_ne_nil_iff
theorem
{l : List α} : List.mapIdx f l ≠ [] ↔ l ≠ []
theorem mapIdx_ne_nil_iff {l : List α} :
List.mapIdxList.mapIdx f l ≠ []List.mapIdx f l ≠ [] ↔ l ≠ [] := by
simp
List.exists_of_mem_mapIdx
theorem
{b : β} {l : List α} (h : b ∈ mapIdx f l) : ∃ (i : Nat) (h : i < l.length), f i l[i] = b
theorem exists_of_mem_mapIdx {b : β} {l : List α}
(h : b ∈ mapIdx f l) : ∃ (i : Nat) (h : i < l.length), f i l[i] = b := by
rw [mapIdx_eq_mapFinIdx] at h
simpa [Fin.exists_iff] using exists_of_mem_mapFinIdx h
List.mem_mapIdx
theorem
{b : β} {l : List α} : b ∈ mapIdx f l ↔ ∃ (i : Nat) (h : i < l.length), f i l[i] = b
@[simp] theorem mem_mapIdx {b : β} {l : List α} :
b ∈ mapIdx f lb ∈ mapIdx f l ↔ ∃ (i : Nat) (h : i < l.length), f i l[i] = b := by
constructor
· intro h
exact exists_of_mem_mapIdx h
· rintro ⟨i, h, rfl⟩
rw [mem_iff_getElem]
exact ⟨i, by simpa using h, by simp⟩
List.mapIdx_eq_cons_iff
theorem
{l : List α} {b : β} :
mapIdx f l = b :: l₂ ↔ ∃ (a : α) (l₁ : List α), l = a :: l₁ ∧ f 0 a = b ∧ mapIdx (fun i => f (i + 1)) l₁ = l₂
theorem mapIdx_eq_cons_iff {l : List α} {b : β} :
mapIdxmapIdx f l = b :: l₂ ↔
∃ (a : α) (l₁ : List α), l = a :: l₁ ∧ f 0 a = b ∧ mapIdx (fun i => f (i + 1)) l₁ = l₂ := by
cases l <;> simp [and_assoc]
List.mapIdx_eq_cons_iff'
theorem
{l : List α} {b : β} :
mapIdx f l = b :: l₂ ↔ l.head?.map (f 0) = some b ∧ l.tail?.map (mapIdx fun i => f (i + 1)) = some l₂
theorem mapIdx_eq_cons_iff' {l : List α} {b : β} :
mapIdxmapIdx f l = b :: l₂ ↔
l.head?.map (f 0) = some b ∧ l.tail?.map (mapIdx fun i => f (i + 1)) = some l₂ := by
cases l <;> simp
List.mapIdx_eq_singleton_iff
theorem
{l : List α} {f : Nat → α → β} {b : β} : mapIdx f l = [b] ↔ ∃ (a : α), l = [a] ∧ f 0 a = b
@[simp] theorem mapIdx_eq_singleton_iff {l : List α} {f : Nat → α → β} {b : β} :
mapIdxmapIdx f l = [b] ↔ ∃ (a : α), l = [a] ∧ f 0 a = b := by
simp [mapIdx_eq_cons_iff]
List.mapIdx_eq_iff
theorem
{l : List α} : mapIdx f l = l' ↔ ∀ i : Nat, l'[i]? = l[i]?.map (f i)
theorem mapIdx_eq_iff {l : List α} : mapIdxmapIdx f l = l' ↔ ∀ i : Nat, l'[i]? = l[i]?.map (f i) := by
constructor
· intro w i
simpa using congrArg (fun l => l[i]?) w.symm
· intro w
ext1 i
simp [w]
List.mapIdx_eq_append_iff
theorem
{l : List α} :
mapIdx f l = l₁ ++ l₂ ↔
∃ (l₁' : List α) (l₂' : List α), l = l₁' ++ l₂' ∧ mapIdx f l₁' = l₁ ∧ mapIdx (fun i => f (i + l₁'.length)) l₂' = l₂
theorem mapIdx_eq_append_iff {l : List α} :
mapIdxmapIdx f l = l₁ ++ l₂ ↔
∃ (l₁' : List α) (l₂' : List α), l = l₁' ++ l₂' ∧
mapIdx f l₁' = l₁ ∧
mapIdx (fun i => f (i + l₁'.length)) l₂' = l₂ := by
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_append_iff]
simp only [mapFinIdx_eq_mapIdx, exists_and_left, exists_prop]
constructor
· rintro ⟨l₁, rfl, l₂, rfl, h⟩
refine ⟨l₁, l₂, by simp_all⟩
· rintro ⟨l₁, l₂, rfl, rfl, rfl⟩
refine ⟨l₁, rfl, l₂, by simp_all⟩
List.mapIdx_eq_mapIdx_iff
theorem
{l : List α} : mapIdx f l = mapIdx g l ↔ ∀ i : Nat, (h : i < l.length) → f i l[i] = g i l[i]
theorem mapIdx_eq_mapIdx_iff {l : List α} :
mapIdxmapIdx f l = mapIdx g l ↔ ∀ i : Nat, (h : i < l.length) → f i l[i] = g i l[i] := by
constructor
· intro w i h
simpa [h] using congrArg (fun l => l[i]?) w
· intro w
apply ext_getElem
· simp
· intro i h₁ h₂
simp [w]
List.mapIdx_set
theorem
{l : List α} {i : Nat} {a : α} : (l.set i a).mapIdx f = (l.mapIdx f).set i (f i a)
@[simp] theorem mapIdx_set {l : List α} {i : Nat} {a : α} :
(l.set i a).mapIdx f = (l.mapIdx f).set i (f i a) := by
simp only [mapIdx_eq_iff, getElem?_set, length_mapIdx, getElem?_mapIdx]
intro i
split
· split <;> simp_all
· rfl
List.head_mapIdx
theorem
{l : List α} {f : Nat → α → β} {w : mapIdx f l ≠ []} : (mapIdx f l).head w = f 0 (l.head (by simpa using w))
@[simp] theorem head_mapIdx {l : List α} {f : Nat → α → β} {w : mapIdxmapIdx f l ≠ []} :
(mapIdx f l).head w = f 0 (l.head (by simpa using w)) := by
cases l with
| nil => simp at w
| cons _ _ => simp
List.head?_mapIdx
theorem
{l : List α} {f : Nat → α → β} : (mapIdx f l).head? = l.head?.map (f 0)
List.getLast_mapIdx
theorem
{l : List α} {f : Nat → α → β} {h} : (mapIdx f l).getLast h = f (l.length - 1) (l.getLast (by simpa using h))
@[simp] theorem getLast_mapIdx {l : List α} {f : Nat → α → β} {h} :
(mapIdx f l).getLast h = f (l.length - 1) (l.getLast (by simpa using h)) := by
cases l with
| nil => simp at h
| cons _ _ =>
simp only [← getElem_cons_length rfl]
simp only [mapIdx_cons]
simp only [← getElem_cons_length rfl]
simp only [← mapIdx_cons, getElem_mapIdx]
simp
List.getLast?_mapIdx
theorem
{l : List α} {f : Nat → α → β} : (mapIdx f l).getLast? = (getLast? l).map (f (l.length - 1))
@[simp] theorem getLast?_mapIdx {l : List α} {f : Nat → α → β} :
(mapIdx f l).getLast? = (getLast? l).map (f (l.length - 1)) := by
cases l
· simp
· rw [getLast?_eq_getLast, getLast?_eq_getLast, getLast_mapIdx] <;> simp
List.mapIdx_mapIdx
theorem
{l : List α} {f : Nat → α → β} {g : Nat → β → γ} : (l.mapIdx f).mapIdx g = l.mapIdx (fun i => g i ∘ f i)
@[simp] theorem mapIdx_mapIdx {l : List α} {f : Nat → α → β} {g : Nat → β → γ} :
(l.mapIdx f).mapIdx g = l.mapIdx (fun i => g i ∘ f i) := by
simp [mapIdx_eq_iff]
List.mapIdx_eq_replicate_iff
theorem
{l : List α} {f : Nat → α → β} {b : β} :
mapIdx f l = replicate l.length b ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] = b
theorem mapIdx_eq_replicate_iff {l : List α} {f : Nat → α → β} {b : β} :
mapIdxmapIdx f l = replicate l.length b ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] = b := by
simp only [eq_replicate_iff, length_mapIdx, mem_mapIdx, forall_exists_index, true_and]
constructor
· intro w i h
apply w _ _ _ rfl
· rintro w _ i h rfl
exact w i h
List.mapIdx_reverse
theorem
{l : List α} {f : Nat → α → β} : l.reverse.mapIdx f = (mapIdx (fun i => f (l.length - 1 - i)) l).reverse
@[simp] theorem mapIdx_reverse {l : List α} {f : Nat → α → β} :
l.reverse.mapIdx f = (mapIdx (fun i => f (l.length - 1 - i)) l).reverse := by
simp [mapIdx_eq_iff]
intro i
by_cases h : i < l.length
· simp [getElem?_reverse, h]
congr
omega
· simp at h
rw [getElem?_eq_none (by simp [h]), getElem?_eq_none (by simp [h])]
simp