Sorting an array of alphanumeric strings 排序包含字母数字字符串的数组

huangapple go评论46阅读模式
英文:

Sorting an array of alphanumeric strings

问题

I want to sort a list of names(not precisely names but alphanumeric strings) such that all names that start with a digit go to the end of the list and are sorted individually. While all names that start with an English alphabet come to the start of the list and are individually sorted. Case sensitivity does not matter e.g 'Apple' is treated the same as 'appLE'.

我想对一个名单进行排序(不一定是名字,而是字母数字字符串),使所有以数字开头的名称都排在列表的末尾,并分别排序。而所有以英文字母开头的名称都排在列表的开头,并分别排序。大小写不敏感,例如 'Apple' 与 'appLE' 被视为相同。

I tried the following code:

我尝试了以下代码:

void main() {
  List<String> names = ['782Agh1', 'Umas', 'apple', 'John', '32'];

  names.sort((String name1, String name2) {
    bool n1StartsWithDigit = name1.startsWith(RegExp(r'[0-9]'));
    bool n2StartsWithDigit = name2.startsWith(RegExp(r'[0-9]'));

    if (!n1StartsWithDigit && !n2StartsWithDigit) {
      // If both names do not start with a digit
      return name1.toLowerCase().compareTo(name2.toLowerCase());
    }
    // Cases when one name starts with a digit and the other does not
    if (n1StartsWithDigit && !n2StartsWithDigit) {
      return name2.compareTo(name1);
    }
    if (!n1StartsWithDigit && n2StartsWithDigit) {
      return name1.compareTo(name2);
    }
    // Both names start with a digit
    return name1.compareTo(name2);
  });

  print(names);
}

and my expected outcome is [apple, John, Umas, 32, 782Agh1]

我的预期结果是 [apple, John, Umas, 32, 782Agh1]。

英文:

I want to sort a list of names(not precisely names but alphanumeric strings) such that all names that start with a digit go to end of list and are sorted individually. While all names that start with an English alphabet come to the start of list and are individually sorted. Case sensitivity does not matter e.g 'Apple' is treated same as 'appLE'.

I tried the following code

void main() {
  List&lt;String&gt; names = [&#39;782Agh1&#39;, &#39;Umas&#39;, &#39;apple&#39;, &#39;John&#39;, &#39;32&#39;];

  names.sort((String name1, String name2) {
    bool n1StartsWithDigit = name1.startsWith(RegExp(r&#39;[0-9]&#39;));
    bool n2StartsWithDigit = name2.startsWith(RegExp(r&#39;[0-9]&#39;));

    if (!n1StartsWithDigit &amp;&amp; !n2StartsWithDigit) {
      //If both names do not start with a digit
      return name1.toLowerCase().compareTo(name2.toLowerCase());
    }
    //Cases when one name starts with a digit and other does not
    if (n1StartsWithDigit &amp;&amp; !n2StartsWithDigit) {
      return name2.compareTo(name1);
    }
    if (!n1StartsWithDigit &amp;&amp; n2StartsWithDigit) {
      return name1.compareTo(name2);
    }
    //Both names start with digit
    return name1.compareTo(name2);
  });

  print(names);
}

and my expected outcome is [apple, John, Umas, 32, 782Agh1]

答案1

得分: 2

以下是已翻译好的代码部分:

void main() {
  List<String> names = ['782Agh1', 'Umas', 'apple', 'John', '32'];

  names.sort((String a, String b) {
    // 确定a或b是否以数字开头
    bool ad = a.startsWith(RegExp(r'[0-9]'));
    bool bd = b.startsWith(RegExp(r'[0-9]'));

    // ^ 是异或运算符,如果一个为真,另一个为假,则返回真
    if (ad ^ bd) {
      // 因此,一个字符串以数字开头,另一个不是
      // 如果a以数字开头,它必须在b之后排序 => 返回1
      // 如果b以数字开头,它必须在a之后排序 => 返回-1
      return ad ? 1 : -1;
    }

    // 两者都以数字或字母开头
    // 像通常一样比较它们
    return a.toLowerCase().compareTo(b.toLowerCase());
  });

  print(names);
}

请注意,我只提供了代码的翻译部分,没有额外的内容。

英文:

The following should do the trick. See comments in the code for explanation

void main() {
  List&lt;String&gt; names = [&#39;782Agh1&#39;, &#39;Umas&#39;, &#39;apple&#39;, &#39;John&#39;, &#39;32&#39;];
   
  
  names.sort((String a, String b) {
    //determines wheter a or b start with a digit
    bool ad = a.startsWith(RegExp(r&#39;[0-9]&#39;));
    bool bd = b.startsWith(RegExp(r&#39;[0-9]&#39;));  
    
    // ^ is the XOR operator, which returns true if one is true and the other false
    if (ad^bd) {
      //so one string starts with a digit, the other not
      //if a starts with a digit, it has to be sorted after b =&gt; return 1
      //if b starts with a digit, it has to be sorted after a =&gt; return -1
      return ad ? 1 : -1;
    }
    
    //both start either with a digit or a alphabetic character
    //compare them as usual
    return a.toLowerCase().compareTo(b.toLowerCase());
  });
  
  print(names);
}

答案2

得分: 0

以下是您要翻译的内容:

"Just for completeness, the 'starts with digit' code is not particularly efficient. Here is a, possibly, more efficient version:

bool _startsWithDigit(String string) =>
    string.isNotEmpty && string.codeUnitAt(0) ^ 0x30 <= 9;

// Ignores case of ASCII letters in strings.
int _compareIgnoreAsciiCase(String a, String b) {
  for (var i = 0; i < a.length && i < b.length; i++) {
    var ca = a.codeUnitAt(i);
    var cb = a.codeUnitAt(i);
    var delta = ca ^ cb;
    if (delta == 0) continue;
    if (delta == 0x20) {
      var uca = ca | 0x20; // Upper case if letter.
      if (0x61 <= uca && uca <= 0x7A) continue;
    }
    return ca - cb;
  }
  return a.length - b.length;
}

int compareWithNumbersLast(String a, String b) {
  var da = _startsWithDigit(a); // A starts with digit?
  var db = _startsWithDigit(b); // B starts with digit?
  if (da) {
    if (!db) return 1;
  } else if (db) {
    return -1;
  } 
  return _compareIgnoreAsciiCase(a, b);
}
```"

<details>
<summary>英文:</summary>

Just for completeness, the &quot;starts with digit&quot; code is not particularly efficient. Here is a, possibly, more efficient version:
```dart
bool _startsWithDigit(String string) =&gt; 
    string.isNotEmpty &amp;&amp; string.codeUnitAt(0) ^ 0x30 &lt;= 9;

// Ignores case of ASCII letters in strings.
int _compareIgnoreAsciiCase(String a, String b) {
  for (var i = 0; i &lt; a.length &amp;&amp; i &lt; b.length; i++) {
    var ca = a.codeUnitAt(i);
    var cb = a.codeUnitAt(i);
    var delta = ca ^ cb;
    if (delta == 0) continue;
    if (delta == 0x20) {
      var uca = ca | 0x20; // Upper case if letter.
      if (0x61 &lt;= uca &amp;&amp; uca &lt;= 0x7A) continue;
    }
    return ca - cb;
  }
  return a.length - b.length;
}

int compareWithNumbersLast(String a, String b) {
  var da = _startsWithDigit(a); // A starts with digit?
  var db = _startsWithDigit(b); // B starts with digit?
  if (da) {
    if (!db) return 1;
  } else if (db) {
    return -1;
  } 
  return _compareIgnoreAsciiCase(a, b);
}

huangapple
  • 本文由 发表于 2023年5月25日 21:48:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76333025.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定