如何返回第一个非空字符串?

时间:2017-07-27 06:51:20

标签: rust

以下Python代码返回第一个非空字符串(在此示例中为bar的内容):

foo = ""
bar = "hello"
foo or bar # returns "hello"

如何在Rust中编写它?我试过这个:

let foo = "";
let bar = "";
foo || bar;

但我得到了这个

error[E0308]: mismatched types
 --> src/main.rs:4:5
  |
4 |     foo || bar;
  |     ^^^ expected bool, found &str
  |
  = note: expected type `bool`
             found type `&str`

我想我不能轻易做我在Python中用Rust做的事情吗?

4 个答案:

答案 0 :(得分:4)

Rust没有像Python这样的 truthy falsy 值的概念,所以你不能使用str作为布尔值。事实上,除了实际的bool和比较运算符之外,你不能使用任何东西。

使用match的{​​{3}}的替代方法是

let result = match (foo.is_empty(), bar.is_empty) {
    (true,_) => Some(foo),
    (_, true) => Some(bar),
    _ => None,
};

如果您想要多种字符串的此类型或功能,可以使用宏:

macro_rules! first_nonempty {
   ( $( $string:expr),+ )=> ({
        $(
            if !$string.is_empty() {
                Some($string)
            } else
        )+
        { None }
   })
}

像这样使用

let res = first_nonempty!("foo", "bar", ""); // res is Some("foo")
let res = first_nonempty!("", "bar", "baz", "quux"); // res is Some("bar")
let res = first_nonempty!(""); // res is None

答案 1 :(得分:3)

如果你有几个字符串,我会使用迭代器;

let strs = ["", "foo", "bar"];
let non_empty = strs.iter().skip_while(|&x| x.is_empty()).next();

println!("{}", non_empty.unwrap_or(&""));

如果您经常使用它,它也可以进入它自己的功能:

// call as let non_empty = first_non_empty(&["", "foo", "bar"]);
fn first_non_empty<'a>(strs: &[&'a str]) -> &'a str {
    strs.iter().skip_while(|&x| x.is_empty()).next().unwrap_or(&"")
}

答案 2 :(得分:3)

您还可以创建一个可以添加所需行为的扩展特征:

trait Or: Sized {
    fn or(self, other: Self) -> Self;
}

impl<'a> Or for &'a str {
    fn or(self, other: &'a str) -> &'a str {
        if self.is_empty() { other } else { self }
    }
}

现在您可以像这样使用它:

assert_eq!("foo".or("bar"), "foo");
assert_eq!("".or("").or("baz").or("").or("quux"), "baz");

如果您需要确保第二个参数被懒惰地评估,您可以使用以下方法扩展Or特征:

fn or_else<F: FnOnce() -> Self>(self, f: F) -> Self;

有关详细信息,请参阅OptionOption#orOption#or_else的类似方法。

答案 3 :(得分:1)

这里的问题是Rust不会在逻辑表达式中隐式地将字符串(或其他任何东西)转换为布尔值。

如果你想模仿Python的行为,即你想在你的布尔表达式之后保留字符串,你必须更明确地使用你的代码,例如:

if foo != "" {
    foo
} else if bar != "" {
    bar
} else {
    ""
}