Repository: nushell/nushell
File: crates/nu-command/src/math/mode.rs (Rust)

Code before:

pub fn mode(values: &[Value], _span: Span, head: Span) -> Result<Value, ShellError> {
    //In e-q, Value doesn't implement Hash or Eq, so we have to get the values inside
    // But f64 doesn't implement Hash, so we get the binary representation to use as
    // key in the HashMap
    let hashable_values = values
        .iter()
        .filter(|x| !x.as_float().is_ok_and(f64::is_nan))
        .map(|val| match val {
            Value::Int { val, .. } => Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Int)),
            Value::Duration { val, .. } => {
                Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Duration))
            }
            Value::Float { val, .. } => {
                Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Float))
            }
            Value::Filesize { val, .. } => Ok(HashableType::new(
                val.get().to_ne_bytes(),
                NumberTypes::Filesize,
            )),
            Value::Error { error, .. } => Err(*error.clone()),
            other => Err(ShellError::UnsupportedInput {
                msg: "Unable to give a result with this input".to_string(),
                input: "value originates from here".into(),
                msg_span: head,
                input_span: other.span(),
            }),
        })
        .collect::<Result<Vec<HashableType>, ShellError>>()?;

    let mut frequency_map = HashMap::new();
    for v in hashable_values {
        let counter = frequency_map.entry(v).or_insert(0);
        *counter += 1;
    }

    let mut max_freq = -1;
    let mut modes = Vec::<Value>::new();
    for (value, frequency) in &frequency_map {
        match max_freq.cmp(frequency) {
            Ordering::Less => {
                max_freq = *frequency;
                modes.clear();
                modes.push(recreate_value(value, head));
            }
            Ordering::Equal => {
                modes.push(recreate_value(value, head));
            }
            Ordering::Greater => (),
        }
    }

Review comment (bug):
While debugging:

Before this change
![image](https://github.com/user-attachments/assets/0ad95125-814a-4d55-9821-e245849a70e6)

After this change
![image](https://github.com/user-attachments/assets/ac137524-44fe-48aa-992f-91c0d7f72659)

But in the end I removed the possibility for this command to accept ranges, so you won't see it. Now:

![image](https://github.com/user-attachments/assets/5d9a2e32-7116-439f-a145-36d49ff113a4)


Code after:

pub fn mode(values: &[Value], span: Span, head: Span) -> Result<Value, ShellError> {
    //In e-q, Value doesn't implement Hash or Eq, so we have to get the values inside
    // But f64 doesn't implement Hash, so we get the binary representation to use as
    // key in the HashMap
    let hashable_values = values
        .iter()
        .filter(|x| !x.as_float().is_ok_and(f64::is_nan))
        .map(|val| match val {
            Value::Int { val, .. } => Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Int)),
            Value::Duration { val, .. } => {
                Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Duration))
            }
            Value::Float { val, .. } => {
                Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Float))
            }
            Value::Filesize { val, .. } => Ok(HashableType::new(
                val.get().to_ne_bytes(),
                NumberTypes::Filesize,
            )),
            Value::Error { error, .. } => Err(*error.clone()),
            _ => Err(ShellError::UnsupportedInput {
                msg: "Unable to give a result with this input".to_string(),
                input: "value originates from here".into(),
                msg_span: head,
                input_span: span,
            }),
        })
        .collect::<Result<Vec<HashableType>, ShellError>>()?;

    let mut frequency_map = HashMap::new();
    for v in hashable_values {
        let counter = frequency_map.entry(v).or_insert(0);
        *counter += 1;
    }

    let mut max_freq = -1;
    let mut modes = Vec::<Value>::new();
    for (value, frequency) in &frequency_map {
        match max_freq.cmp(frequency) {
            Ordering::Less => {
                max_freq = *frequency;
                modes.clear();
                modes.push(recreate_value(value, head));
            }
            Ordering::Equal => {
                modes.push(recreate_value(value, head));
            }
            Ordering::Greater => (),
        }
    }