Rust中的闭包向量



我使用一个XLFormula_engine来计算数据库中非常大量的变量,使用的公式也存储在数据库中。

这是一个带有库的基本示例:
extern crate xlformula_engine;
use xlformula_engine::calculate;
use xlformula_engine::parse_formula;
use xlformula_engine::types;
use xlformula_engine::NoCustomFunction;
let data_function = |s: String| match s.as_str() {
"A" => types::Value::Number(10.12),
"B" => types::Value::Number(123.0),
_ => types::Value::Error(types::Error::Value),
};
let formula = parse_formula::parse_string_to_formula(&"=IF(A>0,B/A,0)", None::<NoCustomFunction>);
let result = calculate::calculate_formula(formula, Some(&data_function));

我怎么能进入一个结果向量这得到公式," a ","B"变量作为向量?

现在我认为我应该删除Rust语言术语并重新表述这个问题:

在一个数据库中,我有大量的复合公式,例如

var | formula 
k | a/b
j | if(a>0,a/b,0)
x | sum(r)

在另一个表中,我有公式中变量的值,例如

var | value
a | 20.9
b | 55.8
r | 3.8

是否有可能使用上面提到的库或等效的库来解决这个问题?

您是否正在寻找类似

let aa = [0.0, 1.0, 2.0];
let bb = [42.0, 4.2, 84.0];
let formula =
parse_formula::parse_string_to_formula(&"=IF(A>0,B/A,0)", None::<NoCustomFunction>);
let results = Iterator::zip(aa.iter(), bb.iter())
.map(|(&a, &b)| {
calculate::calculate_formula(
formula.clone(),
Some(&|s: String| match s.as_str() {
"A" => types::Value::Number(a),
"B" => types::Value::Number(b),
_ => types::Value::Error(types::Error::Value),
}),
)
})
.collect::<Vec<_>>();

// results is [Number(0.0), Number(4.2), Number(42.0)]

aa,bbresults是我根据对你问题中最后一句话的解释而提出的一些例子。如果不是这样:对于SO问题,将这种简短的示例作为输入和输出数据通常会有所帮助。


好吧,再想想。

use xlformula_engine::{
calculate::calculate_formula,
parse_formula::{self, parse_string_to_formula},
types::Value,
NoCustomFunction,
};
let vals = [("a", 20.9), ("b", 55.8), ("r", 3.8)];
let forms = [
("k", "=a/b"),
("j", "=IF(a>0,a/b,0)"),
("x", "=SUM(r)"),
("y", "=x + k + a"),
("u", "=v"),
("v", "=u"),
];
let mut results = HashMap::new();
for (name, value) in vals.iter() {
if results.insert(*name, Value::Number(*value)).is_some() {
return Err("Duplicate value".into());
}
}
let forms = HashMap::from(forms); // TODO: dupe key check?
let results = RefCell::new(results); // calculate_formula wants an Fn, meaning we have to hide the fact we mutate some data. :(
fn invalid() -> Value {
Value::Error(xlformula_engine::types::Error::Reference)
}
fn calc<'vars>(
var: &str,
forms: &HashMap<&'vars str, &str>,
results: &RefCell<HashMap<&'vars str, Value>>,
) -> Value {
if let Some(res) = results.borrow().get(var) {
return res.clone();
}
let Some((var, formula)) = forms.get_key_value(var) else { return invalid() }; // replace var here because the keys of forms have a longer lifetime
results.borrow_mut().insert(var, invalid()); // Hedge against infinite recursion due to mutually recursive formulas
let res = calculate_formula(
parse_string_to_formula(formula, None::<NoCustomFunction>),
Some(&|s: String| {
// stacker magic prevents stack overflows
stacker::maybe_grow(32 * 1024, 1024 * 1024, || calc(&s, forms, results))
}),
);
assert!(results.borrow_mut().insert(var, res.clone()).is_some());
res
}
stacker::maybe_grow(32 * 1024, 1024 * 1024, || {
forms.keys().for_each(|var| {
calc(var, &forms, &results);
})
});
println!("{results:#?}");

最新更新