【问题标题】:Accessing a character in a borrowed string by index按索引访问借用字符串中的字符
【发布时间】:2015-04-10 02:42:10
【问题描述】:

如何通过索引访问借用字符串中的元素?

在 Python 中直截了当:

my_string_lst = list(my_string) 
print my_string_list[0]
print my_string[0]                # same as above

生锈(尝试 1):

let my_string_vec = vec![my_string];    # doesn't work
println!("{}", my_string_vec[0]);       # returns entire of `my_string` 

生锈(尝试 2):

let my_string_vec = my_string.as_bytes();  # returns a &[u8]
println!("{}", my_string_vec[0]);          # prints nothing

我的最终目标是将它放入这样的循环中:

for pos in 0..my_string_vec.len() {
    while shift <= pos && my_string_vec[pos] != my_string_vec[pos-shift] {
        shift += shifts[pos-shift];
    }
    shifts[pos+1] = shift;
}

for ch in my_string_vec {
    let pos = 0;    // simulate some runtime index
    if my_other_string_vec[pos] != ch {
        ...
    }
}

我认为可以在我的条件语句中使用my_string_vec.as_bytes()[pos]和my_string_vec.as_bytes()[pos-shift],但我觉得这有一种不好的代码味道。

【问题讨论】:

标签: rust


【解决方案1】:

您可以使用char_at(index) 访问特定字符。如果要迭代字符串中的字符,可以使用chars() 方法,该方法会生成字符串中字符的迭代器。

特别无法使用索引语法的原因是,IIRC,因为索引语法会给人一种印象,就像访问典型的类似 C 字符串的字符串中的字符一样,其中访问给定索引处的字符是恒定时间操作(即仅访问数组中的单个字节)。另一方面,Rust 中的字符串是 Unicode,单个字符可能不一定只包含一个字节,这使得特定字符访问线性时间操作,因此决定明确和明确地说明这种性能差异。

据我所知,没有可用于交换字符串中字符的方法(请参阅this question)。请注意,无论如何通过不可变借用的字符串这是不可能的,因为这样的字符串不是您可以修改的。如果您要严格交换,您很可能必须使用 String,或者可能是 &amp;mut str,但我对 Unicode 的复杂性不太熟悉。

我建议您按照自己的方式构建String,这样您就不必担心借用字符串的可变性。您将参考/查看借用的字符串,并根据您的逻辑相应地写入输出/构建字符串。

所以这个:

for pos in 0..my_string_vec.len() {
    while shift <= pos && my_string_vec[pos] != my_string_vec[pos-shift] {
        shift += shifts[pos-shift];
    }
    shifts[pos+1] = shift;
}

可能会变成这样(未经测试;不清楚您的逻辑是什么):

for ch in my_string.chars()
    while shift <= pos && ch != my_string.char_at(pos - shift) {
        // assuming shifts is a vec; not clear in question
        shift += shifts[pos - shift];
    }

    shifts.push(shift);
}

你的最后一个 for 循环:

for ch in my_string_vec {
    let pos = 0;    // simulate some runtime index
    if my_other_string_vec[pos] != ch {
        ...
    }
}

您似乎想将字符串 A 中的给定字符与字符串 B 的相应字符(在相同位置)进行比较。为此,我建议将第一个的 chars 迭代器与第二个进行压缩,例如:

for (left, right) in my_string.chars().zip(my_other_string.chars()) {
  if left != right {
  }
}

请注意,zip() 会在任一迭代器停止后立即停止迭代,这意味着如果字符串的长度不同,那么它只会到达最短的字符串。

如果您需要访问“字符索引”信息,您可以在其中添加.enumerate(),因此上面将更改为:

for (index, (left, right)) in my_string.chars().zip(my_other_string.chars()).enumerate()

【讨论】:

  • 感谢您的详细回复。现在,为什么索引语法在 Rust 中不可用的历史是有道理的。我还没有完成你给我的最后一个 sn-p 但是 .char_at() 方法冒犯了编译器。我得到lib.rs:10:1: 10:22 error: unstable feature lib.rs:10 #![feature(str_char)]。当我解决这个问题时会回复你。
  • 该错误应该有一个 note 消息出现在它下面,告诉你如何绕过它,基本上将 #![feature(str_char)] 添加到你的 crate 根的顶部(例如你的 main.js 的顶部)。 rs 文件,如果它是二进制文件,或者 lib.rs 如果它是一个库)。
  • 是的,最初的编译给了我一个错误,要求我添加str_char 功能;在我将 #[feature(str_char)] 添加到我的 crate 属性后,我得到了上述错误。我猜这个功能已经贬值了。我现在正在调查。
  • 我不认为它已被弃用,否则它会告诉你。您是否有机会在 rust beta 上运行?不稳定的功能在 beta 和其他“稳定”版本中不可用;它们仅在夜间版本中可用。如果您想坚持使用测试版而不是每晚使用,我相信char_at(index) 的替代品将类似于chars().nth(index).unwrap()。
  • @anders 它不会更快(切片只是进行指针运算,chars 确实是一个迭代器,因此很懒惰),除了 ASCII 之外的所有内容都会出错并崩溃。
猜你喜欢
  • 1970-01-01
  • 2017-12-01
  • 2019-05-28
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多