根据数组的元素从数组中提取元素

时间:2018-07-08 23:43:34

标签: javascript arrays algorithm data-structures ecmascript-6

我有一个可以匹配此数据结构任何组合的结果集:

[ ["1st", "FELONY"], ["2nd", "FELONY"],  ["3nd", "FELONY"], ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]]  

所以可能是这样的:

[  ["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]]           

或者这个:

[ ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"]]    

或其他一些元素的组合和顺序。

如果该数组有一个FELONY子数组,那么我想忽略MISDEMEANOR元素,如果存在则只获取“ 1st”,否则获取“ 2nd”,否则获取“ 3rd”。 现在,如果数组不包含FELONY元素,那么我想提取“ 1st” MISDEMEANOR元素(如果存在),否则提取“ 2nd”,否则提取“ 3rd”。

我的解决方案:

var arr = [ ["1st", "FELONY"], ["3nd", "FELONY"], ["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]];
for(var i = 0, found = [], fel1 = false, fel2 = false, fel3 = false, mis1 = false, mis2 = false, mis3 = false; i < arr.length; i++) {
   if(arr[i][0] == "1st" && arr[i][1] == "FELONY"){
       found = arr[i];
       fel1 = true;
   } else if (arr[i][0] == "2nd" && arr[i][1] == "FELONY" && !fel1){
       found = arr[i];
       fel2 = true;
   } else if (arr[i][0] == "3rd" && arr[i][1] == "FELONY" && !fel1 && !fel2){
       found = arr[i];
       fel3 = true;
   } else if (arr[i][0] == "1st" && arr[i][1] == "MISDEMEANOR" && !fel1 && !fel2 && !fel3){
       found = arr[i];
       mis1 = true;
   } else if (arr[i][0] == "2st" && arr[i][1] == "MISDEMEANOR" && !fel1 && !fel2 && !fel3 && !mis1){
       found = arr[i];
       mis2 = true;
   } else if (arr[i][0] == "3st" && arr[i][1] == "MISDEMEANOR" && !fel1 && !fel2 && !fel3 && !mis1){
       found = arr[i];
       mis3 = true;
   }
}


if( match && (match[2] == "FELONY" || match[2] == "MISDEMEANOR") && (found[2] != "FELONY" && found[1] != "1st") ) {
            found = [ match[1], match[2], match[3], match[4] ]
            console.log("FOUND! " + found[1]);
} else {
            console.log(`could not parse ${chargesList[i]}`);
}

console.log(JSON.stringify(found));

完成工作,但有点草率。使用EcmaScript 6功能有更好的方法吗?

5 个答案:

答案 0 :(得分:0)

一个非常简单的版本是:

function mySort(a) {
  return [...a].sort(([aa, ab], [ba, bb]) => (ab + aa).localeCompare(bb + ba))
}

然后像这样使用它:

const [selected] = mySort(arr)

一些注意事项:

  • 我们需要[...a]复制数组,因为sort对其操作的数组进行了变异
  • 之所以如此,是因为F中的FELONY位于M中的MISDEMEANOR以及您的1st2nd和{{1 }}以数字开头
  • 这不是一种高效的方法,但就您而言,这可能很好

如果您确实需要其他字符串进行排序,则可以使用查找表:

3rd

答案 1 :(得分:0)

不确定以下内容是否比您所拥有的更优雅或更完美(请让JS专家在这里发表评论),但我可以提出一些建议

尽管做出了以下粗略的假设:-|

  1. 内部数组(子数组)的第一个索引始终以数字开头,例如1st,2nd等

    1.1数字后面的字母是一位数字(不是> 9)。

var sampleArray = [ ["1st", "FELONY"], ["2nd", "FELONY"],  ["3nd", "FELONY"], ["1st", "MISDEMEANOR"], ["2nd", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]] 
// var sampleArray = [["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]]
// var sampleArray = [["2nd", "FELONY"], ["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"]]
 
var reducedArray = sampleArray.reduce((a,b) => a.concat(b))

// step 1 : to just filter felony if any.
let result = [];
if(reducedArray.includes("FELONY")) {
sampleArray.forEach(a => {if(a.includes("FELONY")) {
    result.push(a);
}})
}else{
result = sampleArray;
}

// step 2: sort and print first

result.sort((a,b) => {
if(a[0].substring(0) < b[0].substring(0)) {
    return -1;
} else if(a[0].substring(0) > b[0].substring(0)){
    return 1;
}
return 0;
})

console.log(result[0]); 

答案 2 :(得分:0)

理想情况下,您只希望遍历一次数组,如果可能的话,请避免使用巨大的if/else if字符串。一种方法是使用一种系统,该系统允许您为每个项目做出唯一的评分,其中最高的分数就是您想要的项目。有许多方法可以执行此操作,但是一种简单的方法是为felonymisdemeanor分配数字,以确保它们比第二维大。重罪/轻罪获得10位,第一,第二,第三名占据第一位。然后,您可以浏览一下数组并找到最高分数:

let scores = {
  FELONY: 20,
  MISDEMEANOR: 10,
  '1st': 3,
  '2nd': 2,
  '3rd': 1
}

let arr = [["2nd", "FELONY"],["2nd", "MISDEMEANOR"], ["1st", "MISDEMEANOR"],["1st", "FELONY"]]

let highest = 0, result
for (item of arr) {
  let score = item.reduce((a, c) => a + scores[c], 0)
  if (score > highest) {
    highest = score
    result = item
  }
}
console.log(result)

这也使编辑首选项或添加不同类别变得非常容易,并且不取决于类别的字母排序顺序。

答案 3 :(得分:0)

您可以轻松地将结构转换为对象结构。适用于任何人数或病房排名后的人。

const list = [ ["1st", "FELONY"], ["2nd", "FELONY"],  ["3nd", "FELONY"], ["1st", "MISDEMEANOR"], ["3rd", "MISDEMEANOR"]]  

let obj = {}
list.forEach((item, index) => {
  obj = {
    ...obj,
    [item[1]] : {
       ...obj[item[1]],
       [item[0]]: index,
    }
  }
})

console.log(obj)

因此您可以看到上面给出的列表,我们的对象看起来像

{
  "FELONY": {
    "1st": 0,
    "2nd": 1,
    "3nd": 2
  },
  "MISDEMEANOR": {
    "1st": 3,
    "3rd": 4
  }
}

现在我们可以将所需的值提取为

const obj = {
  "FELONY": {
    "1st": 0,
    "2nd": 1,
    "3nd": 2
  },
  "MISDEMEANOR": {
    "1st": 3,
    "3rd": 4
  }
}

let nameToLookFor = 'FELONY';
if (!obj[nameToLookFor) {
  nameToLookFor = 'MISDEMEANOR'
}

const found = 
  obj[nameToLookFor]['1st'] || obj[nameToLookFor]['2nd'] || obj[nameToLookFor]['3rd']);

console.log(found)

const obj = {
  "FELONY": {
    "1st": 0,
    "2nd": 1,
    "3nd": 2
  },
  "MISDEMEANOR": {
    "1st": 3,
    "3rd": 4
  }
}

let nameToLookFor = 'FELONY';
if (!obj[nameToLookFor]) {
  nameToLookFor = 'MISDEMEANOR'
}


const found = 
  obj[nameToLookFor]['1st'] || obj[nameToLookFor]['2nd'] || obj[nameToLookFor]['3rd'];

console.log(found)

答案 4 :(得分:0)

function penaltiesSort(data){
    const   felonies = data.filter(subArr => subArr[1] == "FELONY" ),
            misdemeanors = data.filter(subArr => subArr[1] == "MISDEMEANOR");

    function sorter(arr){
      const newarr = [];

      for(let i = 0; i < arr.length; i++){
        newarr[arr[i][0][0] - 1] = arr[i];
      }

      return newarr[0] || newarr[1] || newarr[2];
    }

    return felonies.length > 0 ? sorter(felonies) : sorter(misdemeanors);
}
  • 对于初学者,我建议使用es6过滤器数组方法来分离重罪和轻罪,此方法返回一个数组,该数组包含满足条件的元素,在我们的例子中为“ FELONY”或“ MISDEMEANOR”
  • 我写的第二件事是一个自定义排序器,它接收一个数组,循环遍历它,并通过使用数字我们发现这将是我们较新的索引分配,因此如果遇到“ 1st”,我们将其破坏减小到1,然后从中减去-1,并将其放入newarr的0索引中。发生的是,我们正在利用已经拥有的编号将其放置在其各自的“ place” 中。
  • 自定义排序器的最后一个语句是返回遇到的第一个项目,该项目将取决于我们提供给它的数据,例如[[“” 3rd“,” MISDEMEANOR“],[” 2nd“,” MISDEMEANOR“]]在位置0处没有项目,但在位置1处有项目,因此||声明非常适合这份工作
  • 最后,三元运算通过检查长度来检查是否有重罪,如果是,则返回重罪的排序器结果,否则返回轻罪的结果