Inconsistent output

I've the below data in xlsx sheet:

label 	    | month	| value
------------------------------
celsius 	| Jan	| 22.2
celsius 	| Jan	| 3
fahrenheit  | Feb	| 72
celsius	    | Mar	| 25

And I want to get the numbers as:

celsius = [22.2+3=25.2, 25]
fahrenheit = [72]

The problem I've is, my code below output is not consistant, some times it returns:

celsius = [25.2, 25], fahrenheit = [72]

Sometimes it returns:

celsius = [25, 25.2], fahrenheit = [72]

And in other times it returns:

fahrenheit = [72], celsius = [25.2, 25]

My code is:

// [dependencies] calamine = "0.16.0"
use calamine::{open_workbook, Error, Xlsx, Reader, RangeDeserializerBuilder, DeError};
use std::collections::HashMap;

#[derive(Debug)]
struct Foo {
    label: String,
    month: String,
    value: f64,
}

#[derive(Debug)]
struct Boo {
    label: String,
    value: Vec<f64>,
}

fn main() -> Result<(), Error> {
    let path = format!("{}/temperature.xlsx", env!("CARGO_MANIFEST_DIR"));
   // let path = format!("temperature.xlsx");
    let mut workbook: Xlsx<_> = open_workbook(path)?;
    let range = workbook.worksheet_range("Sheet1")
        .ok_or(Error::Msg("Cannot find 'Sheet1'"))??;

    let iter = RangeDeserializerBuilder::new().from_range(&range)?;
    let mut map: HashMap<(String, String), Foo> = HashMap::new();
	let mut history: HashMap<String, Boo> = HashMap::new();

    iter.map(|r: Result<(String, String, f64), DeError>| match r {
        Ok(result) => {
            let (label, month, value) = result;

			let record = map
				.entry((label.clone(), month.clone()))
				.or_insert(Foo {
					label: label,
					month: month,
					value: 0.0,
				});
			record.value += value;
        }
        Err(e) => println!("Error: {}", e)
    }
    ).count();

	println!("Grouped by location and name: {:?}", map);
	for ((l, _), v) in &map {
		let record = history
			.entry(l.clone())
			.or_insert(Boo {
				label : l.clone(),
				value: vec![0.0],
			});
			record.value.push(v.value);
	}
	println!("Forecast vector: {:?}", history);
   // history.iter_mut().map(|(l, h)| h.value.retain(|&x| x != 0.0)).count(); // remove specific value
    history.iter_mut().map(|(_, h)| h.value.remove(0)).count();  // remove specific index
	println!("Forecast vector tuned:  {:?}", history);
    Ok(())
}

Below the output i got for 2 runs:

C:\Users\hasan.yousef\PycharmProjects\untitled>cargo run
   Compiling untitled v0.1.0 (C:\Users\hasan.yousef\PycharmProjects\untitled)
    Finished dev [unoptimized + debuginfo] target(s) in 1.29s
     Running `target\debug\untitled.exe`
Grouped by location and name: {("celsius", "Mar"): Foo { label: "celsius", month: "Mar", value: 25.0 }, ("celsius", "Jan"): Foo { label: "celsius", month: "Jan", value: 25.2222 }, ("fahrenheit", "Feb"): Foo { l
abel: "fahrenheit", month: "Feb", value: 72.0 }}
Forecast vector: {"fahrenheit": Boo { label: "fahrenheit", value: [0.0, 72.0] }, "celsius": Boo { label: "celsius", value: [0.0, 25.0, 25.2222] }}
Forecast vector tuned:  {"fahrenheit": Boo { label: "fahrenheit", value: [72.0] }, "celsius": Boo { label: "celsius", value: [25.0, 25.2222] }}

C:\Users\hasan.yousef\PycharmProjects\untitled>cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target\debug\untitled.exe`
Grouped by location and name: {("celsius", "Jan"): Foo { label: "celsius", month: "Jan", value: 25.2222 }, ("fahrenheit", "Feb"): Foo { label: "fahrenheit", month: "Feb", value: 72.0 }, ("celsius", "Mar"): Foo
{ label: "celsius", month: "Mar", value: 25.0 }}
Forecast vector: {"celsius": Boo { label: "celsius", value: [0.0, 25.2222, 25.0] }, "fahrenheit": Boo { label: "fahrenheit", value: [0.0, 72.0] }}
Forecast vector tuned:  {"celsius": Boo { label: "celsius", value: [25.2222, 25.0] }, "fahrenheit": Boo { label: "fahrenheit", value: [72.0] }}

You care using a HashMap, and HashMap does not guarantee any order. If you want an order, use BTreeMap

2 Likes

In particular a BTreeMap will provide it in sorted order.

2 Likes

Thanks @KrishnaSannasi and @alice BTreeMap solved it perfectly. appreciated.