【问题标题】:JavaScript: reorder array based on numbers within array itemsJavaScript:根据数组项中的数字重新排序数组
【发布时间】:2018-11-15 01:37:31
【问题描述】:

我正在尝试解读一个数组。该数组包含乱序的字符串项,并附有一个数字以指定顺序应该是什么。我想获取数组项中的数字并重新分配数组项索引以反映该数字。例如var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"]。我有一个函数可以在数组中搜索附加的数字并返回值。现在我想获取返回的值并将其转换为新数组中新项目的索引,例如var unscrambled = []。这是我目前所拥有的:

function unscramblePhrase() {
    var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"];   
    var unscrambled = [];
    for (var counter = 0; counter < scrambled.length; counter++) {
        numPosition = scrambled[counter].search('[0-9]');
        arrayIndex = scrambled[counter].substring(numPosition);
        console.log(arrayIndex);
        unscrambled.push(scrambled[arrayIndex]);
    }
 console.log(unscrambled)
}

我看到我的 arrayIndex 正在从加扰数组项的末尾提取数字,但我尝试根据此变量分配索引位置正在生成一个新加扰数组:["want1", "I0", "pizza4", "eat3", "to2"]

【问题讨论】:

  • 如果字符串包含多个数字怎么办:"abc10def22"?如果有相同编号的字符串:["abc12", "def12"]?如果缺少号码:["abc0", "def3"](缺少2)怎么办?
  • @ibrahimmahrir 也是这么想的。显然,这是一个非常具体的案例。正如 OP 所提到的,他已经有一种从字符串中提取数字的方法。
  • 出于本示例的目的。假设数组包含所有正确的数字 (0-4) 并且没有重复。
  • 你想要什么输出?
  • 我希望它读作“I0 want1 to2 eat3 Pizza4”。

标签: javascript arrays


【解决方案1】:

这不是对数组进行排序的最佳方法,但您的问题是您使用Array.prototype.push,而您应该只是将值分配给unscrambled 中的索引。

unscrambled[arrayIndex] = scrambled[counter];

但真正的方法是使用Array.prototype.sort

function getNum(str){
    return Number(str.substring(str.length -1));
}


unscrambled.sort((a, b) => getNum(a) - getNum(b));

注意:此方法对您的数组in-place 进行排序。这可能好,也可能不好,具体取决于您的要求

但您始终可以在克隆上使用它:

[...unscrambled].sort((a, b) => getNum(a) - getNum(b));

【讨论】:

  • 别忘了先实例化unscrambled数组,比如unscrambled = new Array(scrambled.length);
  • 不,这会产生引用问题,因为数组必须在分配期间动态增长,所有浏览器都不支持,而是预先用正确的大小实例化它
  • @NikosM。哪些浏览器不支持动态增长的数组?
  • @dovidweisz,实际上没有浏览器支持通过随机分配到一个索引位置来动态增长数组。所做的是将索引作为动态属性添加到数组对象中,而不是作为数组索引本身。无论如何细节,最好将整个数组实例化,因为大小是已知的,然后任何索引确实可用于分配而不是简单地在对象中添加动态属性
  • @NikosM。如果您说的是真的,我们可以通过检查array.length来验证它。
【解决方案2】:

您可以通过使用 RegEx 将数组拆分为值和索引,对它们进行排序,然后使用辅助 .map 删除附加信息以返回字符串数组来简化此操作。

scrambled.map(i => 
[i.replace(/\d/g,""), +i.replace(/\D/g,"")])
.sort((a, b) => a[1] - b[1])).map(i => i[0]);

var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"];   

var unscrambled = scrambled.map(i => 
  [i.replace(/\d/g,""), +i.replace(/\D/g,"")])
  .sort((a, b) => a[1] - b[1])
  .map( i => i[0]);

console.log(unscrambled);

【讨论】:

  • 为什么在数组上使用Array.from(新数组,而不是原始数组)?
  • 显然是一个很好的答案,但我认为这对 OP 来说并不是很好,因为他似乎还在学习 JS,这是一个非常花哨的 ES6 sn-p。无论哪种方式,都非常好。
  • @SamCreamer 谢谢!诚然,它看起来很花哨,但实际上相当简单。我认为向你展示可能有点吓人的代码是一件好事,因为它教会了你新的技术和模式。
【解决方案3】:

试试这个(不知道它是否有效):

function unscramblePhrase() { var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"];
var unscrambled = []; for (var counter = 0; counter < scrambled.length; counter++) { numPosition = scrambled[counter].search('[0-9]'); arrayIndex = scrambled[counter].substring(numPosition); console.log(arrayIndex); unscrambled[arrayIndex] = scrambled[counter]; } console.log(unscrambled) }

【讨论】:

    【解决方案4】:

    您也可以尝试使用“Array.sort”,如下所示

    var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"]
    
    let getNumberIndex = (d) => [...d].findIndex(v => Number.isInteger(+v))
    
    let getNumber = (d) => d.slice(getNumberIndex(d))
    
    let unscrambled = scrambled.slice(0).sort((a,b) => getNumber(a) - getNumber(b))
    
    console.log(unscrambled)

    【讨论】:

      【解决方案5】:
      const words = ["I0", "want1", "to2", "eat3", "pizza4"]
      
      words
          .map (w => parseInt (w [--w.length]))
          .sort ()
          .map (i => words.filter (w => w [--w.length] == i) [0].replace (i, ''))
      
      // ["I", "want", "to", "eat", "pizza"]
      

      【讨论】:

        【解决方案6】:

        您可以使用单个循环并获取字符串和索引的部分,将值分配给索引并返回数组。

        var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"],
            result = scrambled.reduce((r, string) => {
                var [s, i] = string.match(/\D+|\d+/g);
                r[i] = s;
                return r;
            }, []);
            
        console.log(result);

        对象更有趣。

        var scrambled = ["pizza4", "to2", "I0", "eat3", "want1"],
            result = Object.assign(
                [],
                ...scrambled.map(s => (([v, k]) => ({ [k]: v }))(s.match(/\D+|\d+/g)))
            );
            
        console.log(result);

        【讨论】:

        • 不错的答案!尽管听起来很愚蠢,但我完全不知道您可以在数组形成之前分配给数组中的任何索引!
        猜你喜欢
        • 2020-06-03
        • 2020-06-17
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-29
        相关资源
        最近更新 更多