Path: blob/main/crates/polars-ops/src/chunked_array/list/get.rs
8415 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;6use crate::series::convert_and_bound_idx_ca;78pub fn lst_get(ca: &ListChunked, index: &Int64Chunked, null_on_oob: bool) -> PolarsResult<Column> {9match index.len() {101 => {11let index = index.get(0);12if let Some(index) = index {13ca.lst_get(index, null_on_oob).map(Column::from)14} else {15Ok(Column::full_null(16ca.name().clone(),17ca.len(),18ca.inner_dtype(),19))20}21},22len if len == ca.len() => {23let tmp = ca.rechunk();24let arr = tmp.downcast_as_array();25let offsets = arr.offsets().as_slice();26let take_by = if ca.null_count() == 0 {27index28.iter()29.enumerate()30.map(|(i, opt_idx)| match opt_idx {31Some(idx) => {32let (start, end) = unsafe {33(*offsets.get_unchecked(i), *offsets.get_unchecked(i + 1))34};35let offset = if idx >= 0 { start + idx } else { end + idx };36if offset >= end || offset < start || start == end {37if null_on_oob {38Ok(None)39} else {40polars_bail!(ComputeError: "get index is out of bounds");41}42} else {43Ok(Some(offset as IdxSize))44}45},46None => Ok(None),47})48.collect::<Result<IdxCa, _>>()?49} else {50index51.iter()52.zip(arr.validity().unwrap())53.enumerate()54.map(|(i, (opt_idx, valid))| match (valid, opt_idx) {55(true, Some(idx)) => {56let (start, end) = unsafe {57(*offsets.get_unchecked(i), *offsets.get_unchecked(i + 1))58};59let offset = if idx >= 0 { start + idx } else { end + idx };60if offset >= end || offset < start || start == end {61if null_on_oob {62Ok(None)63} else {64polars_bail!(ComputeError: "get index is out of bounds");65}66} else {67Ok(Some(offset as IdxSize))68}69},70_ => Ok(None),71})72.collect::<Result<IdxCa, _>>()?73};74let s = Series::try_from((ca.name().clone(), arr.values().clone())).unwrap();75unsafe {76s.take_unchecked(&take_by)77.from_physical_unchecked(ca.inner_dtype())78.map(Column::from)79}80},81_ if ca.len() == 1 => {82if let Some(list) = ca.get(0) {83let idx = convert_and_bound_idx_ca(index, list.len(), null_on_oob)?;84let s = Series::try_from((ca.name().clone(), vec![list])).unwrap();85unsafe {86s.take_unchecked(&idx)87.from_physical_unchecked(ca.inner_dtype())88.map(Column::from)89}90} else {91Ok(Column::full_null(92ca.name().clone(),93ca.len(),94ca.inner_dtype(),95))96}97},98len => polars_bail!(99ComputeError:100"`list.get` expression got an index array of length {} while the list has {} elements",101len, ca.len()102),103}104}105106107