HarmonyOS鸿蒙Next中怎么将汉字数字转换成阿拉伯数字?汉字字符串怎么比较或排序?

HarmonyOS鸿蒙Next中怎么将汉字数字转换成阿拉伯数字?汉字字符串怎么比较或排序? 在文件管理器场景下,用户的文件名字常会混有数字或汉字。

如果直接按默认的方式排序,顺序就乱套了。

比如“第12章”会排在“第3章”前面,因为会先比较“1”和“3”。有汉字数字就更麻烦了,比如“第三回”和“第十二回”,直接比较“三”和“十”。

3 回复

演示图(排序前->排序后):

cke_3607.png cke_7556.png

完整代码:

// 1. 中文数字 → 数值
const cnNum: Record<string, number> = {
  '零': 0,
  '〇': 0,
  '一': 1,
  '二': 2,
  '三': 3,
  '四': 4,
  '五': 5,
  '六': 6,
  '七': 7,
  '八': 8,
  '九': 9,
  '十': 10,
  '百': 100,
  '千': 1000,
  '万': 10000,
  '亿': 100000000
};

// 2. 中文数字解析
function parseCnNumber(s: string): number {
  if (!s || s.length === 0) {
    return 0;
  }

  // 处理简单的一位数
  if (s.length === 1 && cnNum[s] < 10) {
    return cnNum[s];
  }

  let result = 0;
  let current = 0;

  for (let i = 0; i < s.length; i++) {
    const ch = s[i];
    const value = cnNum[ch];

    if (value === undefined) {
      // 跳过非数字字符
      continue;
    }

    if (value < 10) { // 数字 0-9
      current = value;
    } else { // 单位:十、百、千、万、亿
      if (current === 0) {
        // 像"十"这种单独的单位,前面省略了"一"
        current = 1;
      }
      result += current * value;
      current = 0;
    }
  }

  // 加上最后剩余的部分
  result += current;

  return result;
}

// 3. 正则拆分成tokens
function tokenize(str: string): string[] {
  // 匹配连续的阿拉伯数字或中文数字
  return str.split(/(\d+|[零〇一二三四五六七八九十百千万亿]+)/g)
    .filter(Boolean);
}

// 4. 中文数字转阿拉伯数字
function cnToArabic(str: string): string {
  return tokenize(str)
    .map(token => {
      // 如果是阿拉伯数字,直接返回
      if (/^\d+$/.test(token)) {
        return token;
      }

      // 如果是中文数字,解析转换
      if (/^[零〇一二三四五六七八九十百千万亿]+$/.test(token)) {
        return parseCnNumber(token).toString();
      }

      // 其他非数字部分原样返回
      return token;
    })
    .join('');
}

@Entry
@ComponentV2
struct Index {
  @Local files: string[] = [
    "第一十二章 并发",
    "第3章 基础",
    "第五百零一章 版本",
    "第一千章 里程碑",
    "第2章 入门",
    "第1章 引言",
    "第八百零一章 勘误",
    "第一百零三章 附录",
    "第三百四十五章 扩展",
    "第5章 总结",
    "第4章 应用"
  ];

  build() {
    Column({ space: 15 }) {
      Row({ space: 20 }) {
        Button('升序排序')
          .fontSize(16)
          .fontColor(Color.White)
          .backgroundColor(0x007DFF)
          .borderRadius(8)
          .padding(12)
          .width(120)
          .onClick(() => {
            // 升序排序逻辑
            const collator = new Intl.Collator('zh-CN', { numeric: true, sensitivity: 'base' });
            this.files.sort((a, b) => collator.compare(cnToArabic(a), cnToArabic(b)));
          })

        Button('降序排序')
          .fontSize(16)
          .fontColor(Color.White)
          .backgroundColor(0x007DFF)
          .borderRadius(8)
          .padding(12)
          .width(120)
          .onClick(() => {
            // 降序排序逻辑
            const collator = new Intl.Collator('zh-CN', { numeric: true, sensitivity: 'base' });
            this.files.sort((a, b) => collator.compare(cnToArabic(b), cnToArabic(a)));
          })
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)
      .padding({ top: 20, bottom: 10 })

      // 文件列表
      List({ space: 15 }) {
        ForEach(this.files, (item: string) => {
          ListItem() {
            Column({ space: 8 }) {
              Text(item)
                .fontSize(18)
                .fontColor(Color.Black)
                .fontWeight(FontWeight.Medium)
              Text(cnToArabic(item))
                .fontSize(14)
                .fontColor(Color.Gray)
            }
            .width('100%')
            .justifyContent(FlexAlign.Center)
            .alignItems(HorizontalAlign.Start)
          }
          .width('100%')
          .height(100)
          .padding(20)
          .backgroundColor(Color.White)
          .borderRadius(16)
          .border({ width: 1, color: 0xEEEEEE })
        })
      }
      .width('100%')
      .height('100%')
      .layoutWeight(1)
      .padding({ left: 20, right: 20 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor(0xF5F5F5)
  }
}

更多关于HarmonyOS鸿蒙Next中怎么将汉字数字转换成阿拉伯数字?汉字字符串怎么比较或排序?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,汉字数字转阿拉伯数字可使用Intl.NumberFormat或第三方库如chinese-number。字符串比较排序使用localeCompare方法,指定'zh-Hans-CN'区域设置,例如str1.localeCompare(str2, 'zh-Hans-CN')

在HarmonyOS Next中,处理汉字数字转换和字符串比较排序,核心在于实现一个自定义的字符串比较器(Comparator),并在其中解析和转换汉字数字。

1. 汉字数字转阿拉伯数字 你需要一个方法将诸如“三”、“十二”、“一百零五”这样的字符串转换为数字(3, 12, 105)。这通常通过以下步骤实现:

  • 建立映射表:创建汉字字符(零、一、二……九、十、百、千、万)到数值或权重的映射。
  • 解析算法:从左到右扫描字符串,处理“十”、“百”、“千”等量级单位,以及“零”的特殊情况,进行累加计算。对于“第十二回”,你需要先提取出“十二”进行转换。

2. 实现混合字符串比较器 在文件排序场景,你需要一个智能的Comparator<String>

  • 逐字符扫描:将两个字符串(如“第12章”和“第3章”)按字符逐一比较。
  • 识别数字段:当遇到连续的数字字符(‘0’-‘9’)或连续的汉字数字字符时,将它们作为一个完整的数字段提取出来。
  • 转换与比较:将提取出的数字段(无论是阿拉伯数字“12”还是汉字数字“十二”)转换为整数值,然后进行数值比较。数值大的字符串排在后面。
  • 非数字部分:对于非数字的普通字符(如“第”、“章”),直接进行普通的字符(Unicode)比较。
  • 分段决胜:如果当前比较的数字段或字符段相等,则继续比较字符串的下一个段落,直到分出大小或到达字符串末尾。

示例逻辑流程(比较“第12章”和“第3章”):

  1. 比较第一个非数字段“第” vs “第”,相等。
  2. 识别并提取数字段“12” vs “3”。
  3. 将“12”和“3”转为整数12和3,进行数值比较。12 > 3,因此“第12章” 大于 “第3章”。在升序排序中,“第3章”会排在“第12章”前面,符合自然阅读习惯。

关键API与位置 在HarmonyOS Next应用开发中,此逻辑应实现在你为文件列表数据排序的部分。你可以:

  • Array.sort()List.sort()方法中传入自定义的Comparator
  • 如果使用DataAbilityHelper或文件管理相关接口获取列表,通常在数据返回后的展示层进行处理和排序。

注意事项

  • 汉字数字解析需要处理复杂情况,如“两千三百五十六”。
  • 考虑性能,尤其对长列表,可对转换结果进行缓存。
  • 此方法同样适用于混合了英文、数字、汉字的通用文件名排序。

通过实现上述自定义比较逻辑,即可解决文件名中数字部分(无论阿拉伯还是汉字)不按数值大小排序的问题,实现符合用户直觉的自然排序。

回到顶部