【问题标题】:JS array sort with regexJS数组排序与正则表达式
【发布时间】:2015-10-22 06:10:11
【问题描述】:

我的目标是根据使用正则表达式的 JS 对象的优先级对数组进行排序。这是我所拥有的:

JS 对象定义:

var rx_CondoIndicator = new RegExp(/\bCONDO(MINIUM)?(?!S)/);

var rx_TownhouseIndicator = new RegExp(/\bTOWN\s*(HOUSE|HOME)(?!S)/);

var rx_TimeshareIndicator = new RegExp(/\bTIMESHARE(?!S)/);

对定义的对象进行排序:

var so_UnitKeywordIndicator = {
    rx_CondoIndicator: 1,
    rx_TownhouseIndicator: 2,
    rx_TimeshareIndicator: 3
};

arrUnitNumber = ['TIMESHARE A-1', 'TOWNHOUSE 407', 'CONDO #13'] 

以下逻辑会忽略排序对象的优先级,并且不会按照所需的顺序对数组进行排序,即“CONDO #13”、“TOWNHOUSE 407”、“TIMESHARE A-1”

arrUnitNumber.sort(function(x,y){
    return so_UnitKeywordIndicator[x] - so_UnitKeywordIndicator[y];
})

请注意,为简洁起见,仅显示一小部分 JS 排序对象。

如果这不是解决问题的最佳方法,作为 JS 的新手,我愿意接受任何建议。

【问题讨论】:

  • @NRKirby 和我已经为您更正了格式。
  • 您永远不会在 sort 循环中使用正则表达式,xy 将是数组中的条目,so_UnitKeywordIndicator 上不存在这些条目特性。所以so_UnitKeywordIndicator[x] 永远是undefined

标签: javascript arrays regex sorting


【解决方案1】:

主要问题是您永远不会将正则表达式用于sort 循环中的任何内容,并且xy 将是数组中的条目('TIMESHARE A-1' 和类似的),它们不会t 作为属性存在于so_UnitKeywordIndicator。所以so_UnitKeywordIndicator[x] 永远是undefined

您似乎想使用正则表达式对字符串进行分类,然后根据so_UnitKeywordIndicator 中的相关值对它们进行排序。因此,您需要根据正则表达式测试字符串。

如果您从这些字符串开始,我想我可能会这样处理(删除so_UnitKeywordIndicator):

arrUnitNumber.sort(function(x,y){
    return getSortingKey(x) - getSortingKey(y);
});

function getSortingKey(value) {
    if (rx_CondoIndicator.test(value)) {
        return 1;
    }
    if (rx_TownhouseIndicator.test(value)) {
        return 2;
    }
    if (rx_TimeshareIndicator.test(value)) {
        return 3;
    }
    return 4;
}

实例:

var rx_CondoIndicator = /\bCONDO(MINIUM)?(?!S)/;

var rx_TownhouseIndicator = /\bTOWN\s*(HOUSE|HOME)(?!S)/;

var rx_TimeshareIndicator = /\bTIMESHARE(?!S)/;

var arrUnitNumber = ['TIMESHARE A-1', 'TOWNHOUSE 407', 'CONDO #13'];

arrUnitNumber.sort(function(x, y) {
  return getSortingKey(x) - getSortingKey(y);
});

arrUnitNumber.forEach(function(entry) {
  snippet.log(entry);
});

function getSortingKey(value) {
  if (rx_CondoIndicator.test(value)) {
    return 1;
  }
  if (rx_TownhouseIndicator.test(value)) {
    return 2;
  }
  if (rx_TimeshareIndicator.test(value)) {
    return 3;
  }
  return 4;
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

但是,如果有很多条目,那效率很低,因为每次比较数组中的两个条目时它都必须重新计算排序键,即使对于相同的值(可能)也会重复计算。因此,如果有大量条目,您可能最好构建一个对象数组,并在其上添加排序键:

var unitObjects = arrUnitNumber.map(function(entry) {
    return {
        str: entry,
        key: getSortingKey(entry)
    };
});
unitObjects.sort(function(x, y){
    return x.key - y.key;
});

然后要么直接使用那个数组,或者如果你想再次使用字符串,最后只需要map

arrUnitNumber = unitObjects.map(function(entry) {
    return entry.str;
});

但同样,只有当数组中有很多 (lot) 条目时。

实例:

var rx_CondoIndicator = /\bCONDO(MINIUM)?(?!S)/;

var rx_TownhouseIndicator = /\bTOWN\s*(HOUSE|HOME)(?!S)/;

var rx_TimeshareIndicator = /\bTIMESHARE(?!S)/;

var arrUnitNumber = ['TIMESHARE A-1', 'TOWNHOUSE 407', 'CONDO #13'];

var unitObjects = arrUnitNumber.map(function(entry) {
    return {
        str: entry,
        key: getSortingKey(entry)
    };
});
unitObjects.sort(function(x, y){
    return x.key - y.key;
});

unitObjects.forEach(function(entry) {
  snippet.log(entry.str);
});

function getSortingKey(value) {
  if (rx_CondoIndicator.test(value)) {
    return 1;
  }
  if (rx_TownhouseIndicator.test(value)) {
    return 2;
  }
  if (rx_TimeshareIndicator.test(value)) {
    return 3;
  }
  return 4;
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

旁注:您不需要(或不想要)定义正则表达式的new RegExp( 部分,JavaScript 不寻常,因为它具有正则表达式 literals(如字符串文字);这就是你的/.../

var rx_CondoIndicator = /\bCONDO(MINIUM)?(?!S)/;

var rx_TownhouseIndicator = /\bTOWN\s*(HOUSE|HOME)(?!S)/;

var rx_TimeshareIndicator = /\bTIMESHARE(?!S)/;

【讨论】:

  • @TJ - 赞赏 /.../ 建议和格式化想法。我会记得在以后的帖子中使用它们。
【解决方案2】:

首先,将所有正则表达式放入一个数组中。它们的列出顺序将决定它们的排名,其中第一个元素是最高的。

var so_UnitKeywordIndicator = [rx_CondoIndicator, rx_TownhouseIndicator, rx_TimeshareIndicator];

现在这个函数将给出给定单位的排名。

function getSortRank(unit) {
    for (var i = 0; i < so_UnitKeywordIndicator.length; i++) {
        if (so_UnitKeywordIndicator[i].test(unit)) {
            return i;   
        }
    }
    return so_UnitKeywordIndicator.length;
}

最后,您可以使用此函数对单元数组进行排序,如下所示:

var sortedUnits = arrUnitNumber.sort(function(x, y) {
    return getSortRank(x) - getSortRank(y);
});

【讨论】:

    【解决方案3】:

    只是为了分享我的问题和解决方案。我需要按标签订购我的格式数据。

    const nameTagDatas = ["name(ddd)", "name(ccc)", "name(bbb)", "name(aaa)"];
    const tagOrder = ["aaa", "bbb", "ccc", "ddd"];
    
    nameTagDatas.sort(
      (a, b) =>
        tagOrder.findIndex((e) => a.search(new RegExp("\\(" + e + "\\)")) != -1) -
        tagOrder.findIndex((e) => b.search(new RegExp("\\(" + e + "\\)")) != -1)
    );
    
    console.log(nameTagDatas) // [ 'name(aaa)', 'name(bbb)', 'name(ccc)', 'name(ddd)' ]
    

    提取函数

    nameTagDatas.sort(
      (a, b) => findIndexByTag(tagOrder, a) - findIndexByTag(tagOrder, b)
    );
    
    function findIndexByTag(_orderArr, _searchStr) {
      return _orderArr.findIndex(
        (e) => _searchStr.search(new RegExp("\\(" + e + "\\)")) != -1
      );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      • 1970-01-01
      • 2012-01-30
      • 2019-01-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多