Search code examples
algorithmloopsrustvector

Sum fields of a vector depending on condition and get a smaller vector


Let's say I have this struct:

pub struct MyStruct {
    uuid: uuid,
    date: NaiveDate,
    value1: i32,
    value2: i32
    my_type: i8
}

I am looking for a way to combine a vector of this MyStruct so that it does not repeat (pseudocode):

  let all_structs: Vec<MyStruct> = vec![MyStruct, MyStruct , MyStruct ...];
  let structs_per_uuid_and_date = all_structs.into_iter(). { sum specific fields (like value1 and value2) for same combination of uuid and date }

and we discard my_type


Solution

  • You can do this by sorting the Vec and then using dedup_by.

    use chrono::NaiveDate;
    use uuid::Uuid;
    
    pub struct MyStruct {
        uuid: Uuid,
        date: NaiveDate,
        value1: i32,
        value2: i32,
        my_type: i8,
    }
    
    pub fn merge(structs: &mut Vec<MyStruct>) {
        structs.sort_by_key(|s| (s.uuid, s.date));
        structs.dedup_by(|a, b| {
            if a.uuid == b.uuid && a.date == b.date {
                b.value1 += a.value1;
                b.value2 += a.value2;
                true
            } else {
                false
            }
        })
    }
    

    You can't discard a field of a struct.