expr: speed up index from O(N*M) to O(N+M)

This commit is contained in:
Sylvestre Ledru
2026-06-03 20:53:16 +02:00
committed by Daniel Hofstetter
parent 0011d54fbb
commit 22b4c6d15d
2 changed files with 12 additions and 4 deletions
+11 -3
View File
@@ -4,6 +4,7 @@
// file that was distributed with this source code.
use std::cmp::Ordering;
use std::collections::HashSet;
use uucore::{
CharByte, IntoCharByteIterator,
@@ -39,15 +40,22 @@ fn index_with_locale(
// In the UTF-8 case, we try to decode the strings on the fly. We
// compare UTf-8 characters as long as the stream is valid, and
// switch to byte comparison when the byte is an invalid sequence.
// Collect the needle chars into a set first so the search is
// O(N + M) rather than O(N * M).
let needles: HashSet<CharByte> = right.iter_char_bytes().collect();
left.iter_char_bytes()
.position(|ch_h| right.iter_char_bytes().any(|ch_n| ch_n == ch_h))
.position(|ch_h| needles.contains(&ch_h))
.map_or(0, |idx| idx + 1)
}
UEncoding::Ascii => {
// In the default case, we just perform byte-wise comparison on the
// arrays.
// arrays. A 256-entry lookup table keeps this O(N + M).
let mut needles = [false; 256];
for &b in right {
needles[b as usize] = true;
}
left.iter()
.position(|ch_h| right.iter().any(|ch_n| ch_n == ch_h))
.position(|&ch_h| needles[ch_h as usize])
.map_or(0, |idx| idx + 1)
}
}
+1 -1
View File
@@ -601,7 +601,7 @@ macro_rules! prompt_yes(
/// Represent either a character or a byte.
/// Used to iterate on partially valid UTF-8 data
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CharByte {
Char(char),
Byte(u8),