在Android的快速,低功耗/ CPU字符串匹配(Rapid, low power/cpu str

2019-10-30 03:53发布

我工作的一个应用程序,需要语音输入,而输入匹配在清单已知的项目。

清单中的每个项目都有别名列表,这样长的标题项目可以匹配较短的名称。

例如:

class Product
{
  itemname: "Old Stinky's Western Kentucky Big Rig Polish",
  aliases: ["old stinky", "other alias"]
}

然后加载到内存为:

public List<Product> Collection;
Collection.Add(alltheproducts);

然后通过匹配:

public String isProductOrAlias(String lowertext) 
for (Product p: products.Collection) {
    if(lowertext.equals(p.name.toLowerCase()))
        return p.name;
    if(p.aliases != null) {
        for (String s: p.aliases) {
            if(lowertext.equals(s.toLowerCase()))
                return p.name;
        }
    }
}

这是一个检验批次的原型25项伟大的工作,但最终需要处理的尽可能接近实时地在手机上5,000-10,000项目。

核心问题:

假设我可以保留在内存中,这些项目(约64千字节的采样时钟,所以比共10000项兆字节以下)10000,什么是使用Android上对这些对象存储在内存中的最好的收集,什么是以最快的方式来填充数据对象,然后找到匹配的元素?

Answer 1:

您可以轻松地用做这个Map假设没有重复的别名或产品名称。 科特林版本是:

data class Product(val name: String, val aliases: Array<String>)

fun test() {
    val products = listOf<Product>( ... )

    // Do this once, create a map from name and aliases to the product
    val productIndex = products.asSequence().flatMap { product ->
        val allKeys = sequenceOf(product.name) + product.aliases
        allKeys.map { it.toLowerCase() to product }
    }.toMap() 
    // now name => product and each alias => product are mapped in productIndex

    val matchingProduct = productIndex["something"] // search lower case name

    println(matchingProduct?.name ?: "<not found>")
}

除非你是做前缀匹配特里就没有意义了。 A设置是没有意义的,因为你只能告诉“它存在”,而不是“这一点是它匹配”。 一个地图会从什么地方到原来的Product ,从中可以得到的名称。

此外,匹配算法的蛮力重新写在科特林是在回答您的其他问题: https://stackoverflow.com/a/52565549/3679676



文章来源: Rapid, low power/cpu string matching in Android