Path: blob/main/crates/polars-ops/src/chunked_array/list/get.rs
6939 views
use polars_core::prelude::{Column, IdxCa, Int64Chunked, ListChunked};1use polars_core::series::Series;2use polars_error::{PolarsResult, polars_bail};3use polars_utils::IdxSize;45use super::ListNameSpaceImpl;67pub fn lst_get(ca: &ListChunked, index: &Int64Chunked, null_on_oob: bool) -> PolarsResult<Column> {8match index.len() {91 => {10let index = index.get(0);11if let Some(index) = index {12ca.lst_get(index, null_on_oob).map(Column::from)13} else {14Ok(Column::full_null(15ca.name().clone(),16ca.len(),17ca.inner_dtype(),18))19}20},21len if len == ca.len() => {22let tmp = ca.rechunk();23let arr = tmp.downcast_as_array();24let offsets = arr.offsets().as_slice();25let take_by = if ca.null_count() == 0 {26index27.iter()28.enumerate()29.map(|(i, opt_idx)| match opt_idx {30Some(idx) => {31let (start, end) = unsafe {32(*offsets.get_unchecked(i), *offsets.get_unchecked(i + 1))33};34let offset = if idx >= 0 { start + idx } else { end + idx };35if offset >= end || offset < start || start == end {36if null_on_oob {37Ok(None)38} else {39polars_bail!(ComputeError: "get index is out of bounds");40}41} else {42Ok(Some(offset as IdxSize))43}44},45None => Ok(None),46})47.collect::<Result<IdxCa, _>>()?48} else {49index50.iter()51.zip(arr.validity().unwrap())52.enumerate()53.map(|(i, (opt_idx, valid))| match (valid, opt_idx) {54(true, Some(idx)) => {55let (start, end) = unsafe {56(*offsets.get_unchecked(i), *offsets.get_unchecked(i + 1))57};58let offset = if idx >= 0 { start + idx } else { end + idx };59if offset >= end || offset < start || start == end {60if null_on_oob {61Ok(None)62} else {63polars_bail!(ComputeError: "get index is out of bounds");64}65} else {66Ok(Some(offset as IdxSize))67}68},69_ => Ok(None),70})71.collect::<Result<IdxCa, _>>()?72};73let s = Series::try_from((ca.name().clone(), arr.values().clone())).unwrap();74unsafe { s.take_unchecked(&take_by) }75.cast(ca.inner_dtype())76.map(Column::from)77},78_ if ca.len() == 1 => {79if ca.null_count() > 0 {80return Ok(Column::full_null(81ca.name().clone(),82index.len(),83ca.inner_dtype(),84));85}86let tmp = ca.rechunk();87let arr = tmp.downcast_as_array();88let offsets = arr.offsets().as_slice();89let start = offsets[0];90let end = offsets[1];91let out_of_bounds = |offset| offset >= end || offset < start || start == end;92let take_by: IdxCa = index93.iter()94.map(|opt_idx| match opt_idx {95Some(idx) => {96let offset = if idx >= 0 { start + idx } else { end + idx };97if out_of_bounds(offset) {98if null_on_oob {99Ok(None)100} else {101polars_bail!(ComputeError: "get index is out of bounds");102}103} else {104let Ok(offset) = IdxSize::try_from(offset) else {105polars_bail!(ComputeError: "get index is out of bounds");106};107Ok(Some(offset))108}109},110None => Ok(None),111})112.collect::<Result<IdxCa, _>>()?;113114let s = Series::try_from((ca.name().clone(), arr.values().clone())).unwrap();115unsafe { s.take_unchecked(&take_by) }116.cast(ca.inner_dtype())117.map(Column::from)118},119len => polars_bail!(120ComputeError:121"`list.get` expression got an index array of length {} while the list has {} elements",122len, ca.len()123),124}125}126127128