【问题标题】:Assigning lexical order score to strings将词汇顺序分数分配给字符串
【发布时间】:2017-03-24 10:09:20
【问题描述】:

在我当前的项目中,我们有一种奇怪的排序系统。

与通过相互比较来确定元素顺序的通常方法相反,我们首先为每个元素分配一个数字分数,然后按此分数进行排序。这样我们就可以通过改变分数分配部分来按照不同的标准进行排序。

我想要的是在字符串上定义一个函数: f(a)

字符串是 unicode,我们应该支持不区分大小写。

这可能吗?

【问题讨论】:

  • 郑重声明:可能我的回答有点笼统;但你的问题也是如此。精细反馈;考虑添加一个minimal reproducible example,以便我们更好地理解这些分数排序和字符串排序是如何协同工作的。
  • 由于 unicode 只是一个 21 位字符集,只需将字符串编码为所有那些 21 位代码点,第一个字符从最高有效位开始并向下。您必须使用BigIntegers。还有,这是cray cray。
  • a.toLowerCase().compareTo(b.toLowerCase()) 呢?
  • @DavidConrad 我不熟悉“cray cray”这个词。这是什么意思?
  • @GhostCat 俚语疯狂。

标签: java string algorithm sorting unicode


【解决方案1】:

不要误会我的意思,但这种方法没有意义。因为这意味着您可以使用 Java 的“默认”机制来解决您的问题;那将是:您创建自己的自定义Comparator

含义:当对某个类的对象的集合/数组进行排序时,合理定义它们的顺序的方法是提供一个比较器,它可以告诉你该类的任何两个对象如何对它们进行排序.

好吧,鉴于您的设置,这可能意味着:您的比较器需要能够根据提供的输入对象计算该分数。然后,它可以使用进一步信息(如字符串值)做出进一步的决定。

再想一想:你真的应该退后一步。如果你有一个已经在使用这个奇怪系统的巨大代码库;那么好吧,您需要定义一个 scoring 函数,将您的字符串简化为数字;并确保分数值与您正在寻找的 f(a) 评分功能的想法。而是简单地使用不同的比较器实现来实现基于不断变化的标准的排序。

【讨论】:

  • 这是一个庞大的代码库,目前无法更改排序系统,所以我正在寻找这样的功能。
【解决方案2】:

我想要的是在字符串上定义一个函数: f(a)

这可能吗?

不,除非您的字符串长度有限,否则不会。假设 f("a") = 1。那么,显然 f("aa") >= 2。继续这个模式,f("aa...a") >= n for "aa...a" 包含n 个符号。因为对于任何这样的字符串 f("aa...a")

请注意,如果您使用 BigDecimal 作为函数的值而不是整数类型,则有一种方法(尽管使用 Unicode 可能有点棘手,基本思想是不规范化字符串并逐字节转换-byte 转换为十进制数字)。

【讨论】:

  • 为什么要使用BigDecimal 而不是BigInteger
  • 伟大的收获;像你们俩一样……指出问题中的逻辑缺陷;以及关于 BigInteger 与 BigDecimal 的微妙但重要的细节;-)
  • @DavidConrad 因为BigInteger 有我的回答中描述的问题。基本上,对于任何两个整数m, n,它们之间只有|m-n|-1 整数(有限多个),对于按字典顺序排列的字符串和BigDecimals 都不是这种情况。 (正式地说,BigInteger 的序数 ω 太小了,BigDecimal 的 ω+ω×Q(我认为...)就足够了。)
  • @Abstraction,如果字符串长度有限怎么办。就像,只有1个字符。有没有一种方法可以为满足这种关系的单个 unicode 字符分配一个数字?
  • @Can 正如我在回答中所说:规范化字符串,采用 UTF-32 之类的字节(我假设字节值较小的符号在字母意义上是“少”),填充它从右边到最大可能长度的零,这将是你的号码。请注意,长度必须在 bytes 中限制,而不是 carnation (因为Unicode允许您将任意数量的修饰符添加到单个字符中 - 例如ด้ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็-反例)
【解决方案3】:

您需要实现自定义比较器。像这样 -

import java.util.Comparator;

public class myString {
    private String s;   
    private int score;
    // getter & setter
    // ...
}


public class ScoredStringComparator implements Comparator<myString>
{
    @Override
    public int compare(myString x, myString y)
    {
        // Assume neither string is null.
        if (x.getScore() < y.getScore())
        {
            return -1;
        }
        if (x.getScore() > y.getScore())
        {
            return 1;
        }
        return 0;
    }
}

并将字符串放入 s TreeSet。

TreeSet<myString> stringSet = new TreeSet<myString>(new ScoredStringComparator());

现在,当您需要更新字符串的分数时,可以以对数时间复杂度进行。

stringSet.remove(aString);
aString.setScore(newScore);
stringSet.add(aString);

【讨论】:

  • 是的,但我不能使用比较器。没有可比较的“其他”元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 2021-07-23
相关资源
最近更新 更多