创建出现在没有空格的字符串中的单词列表 - 当单词出现多次时考虑

Create List of Words that Appear In String Without Spaces - Account For When Word Appears More Than Once

根据 this Codewars challenge,我需要创建一些简单的逻辑来跟踪字符串中出现的所有单词。


说明

一些新收银员开始在您的餐厅工作。

他们擅长接单,但他们不知道如何将单词大写,或使用space bar!

他们创建的所有订单看起来都像这样:

"milkshakepizzachickenfriescokeburgerpizzasandwichmilkshakepizza"

厨房工作人员威胁要辞职,因为订单很难看懂。

他们的偏好是将订单作为带有 space 和大写字母的漂亮干净的字符串,如下所示:

"Burger Fries Chicken Pizza Pizza Pizza Sandwich Milkshake Milkshake Coke"

厨房工作人员希望菜品的顺序与它们在菜单中出现的顺序相同。

菜单项相当简单,项名没有重叠:

  1. 汉堡
  2. 薯条
  3. 鸡肉
  4. 披萨
  5. 三明治
  6. 洋葱圈
  7. 奶昔
  8. 可乐

EDIT 遵循 .match() 逻辑,我创建了一个包含 all 项目的数组,这些项目出现在输入中。但是我不知道根据它们在原始字符串中出现的顺序对它们进行排序的最快方法:

function getOrder(order) {
  
  let menu = ['Burger', 'Fries', 'Chicken', 'Pizza', 'Sandwich', 'Onionrings', 'Milkshake', 'Coke'];
  
  let finalOrder = order.split(/(burger|fries|chicken|pizza|sandwich|onionrings|milkshake|coke)/i);
  finalOrder = finalOrder.filter((element) => element !== null || element !== "");
  finalOrder = finalOrder.map((element) => element.charAt(0).toUpperCase() + element.slice(1));
  finalOrder = finalOrder.sort((a, b) => {
    if (menu.indexOf(a) > menu.indexOf(b)) {
      return 1;
    }
    else {
      return -1;
    }
  });
  return finalOrder.join(" ").trim(/\s/);
}

console.log(getOrder("milkshakepizzachickenfriescokeburgerpizzasandwichmilkshakepizza"));

如果您知道您的单词在字符串中的位置,您可以将其删除,这样如果您再次查看剩余的字符串,就会找到重复项。

使用 indexOf 而不是 includes。这需要第二个参数,即开始搜索的索引。例如,循环遍历所有汉堡,并将上一个索引传递给下一个 indexOf 调用,直到它 returns -1,然后计算你循环的频率。

或者,您可以 .match 基于接受所有可能菜肴的正则表达式的文本。

您还可以逐个字符地迭代并在单词形成时附加它们。要检查一个单词是否为 "formed",您可以使用一个集合来存储有效的 words/menu-items:

function getOrder(input) {

  let order = [];
  const items = new Set(["burger", "fries", "chicken", "pizza", "sandwich", "onionrings", "milkshake", "coke"]);

  let curr = "";
  for (let c of [...input]) {
    curr += c;
    if (items.has(curr)) {
      order.push(curr);
      curr = "";
    }
  }
  return order.map(item => item.charAt(0).toUpperCase() + item.slice(1)).join(" ");
}

console.log(getOrder("milkshakepizzachickenfriescokeburgerpizzasandwichmilkshakepizza"));

按给定顺序创建一个包含小写菜单项的数组

let testString = "milkshakepizzachickenfriescokeburgerpizzasandwichmilkshakepizza";
let menuItemsLowerCase = ["burger","fries","chicken","pizza","sandwich","onionrings","milkshake","coke"];

遍历每个项目并将每个项目的出现替换为项目字符串加逗号

for(let itemIndex=0;itemIndex<menuItemsLowerCase.length; itemIndex++){
    const item = menuItemsLowerCase[itemIndex];
    const re = new RegExp(item,"g");
    testString = testString.replace(re, item+',');
}

去掉最后一个逗号

if(testString[testString.length-1] === ','){
    testString = testString.substr(0,testString.length-1);
}

将字符串拆分为逗号并排序

let stringAsArray = testString.split(',');
stringAsArray = stringAsArray.sort(function(a,b){
    return menuItemsLowerCase.indexOf(a) - menuItemsLowerCase.indexOf(b);
});

将第一个字符转换为大写并以 space 作为分隔符重新加入

console.log(stringAsArray.map(function(item){
        return item.substr(0,1).toUpperCase() + item.substr(1);
    }
).join(' '));

以下是我对这一挑战的解决方案:

解释:

对于每个菜单项:计算该项目出现的次数并将该项目添加到输出字符串中的次数。

  • RegExp(i, 'gi'): 案例 insensitive global match for counting
  • || []: 处理匹配0次
  • .length: 只得到count个匹配项
  • Array().fill(i): 创建大小为菜单项的数组,重复
  • ...: 展开数组以便 push 在数组中单独插入元素
  • .join(' '):最后,在每个匹配之间插入空格

示例:

let menu = ['Burger','Fries','Chicken','Pizza','Sandwich','Onionrings','Milkshake','Coke'];

function getOrder(input) {
  let output = [];
  menu.forEach( (i) =>
    output.push( ...Array( (input.match( RegExp(i, 'gi') ) || []).length ).fill( i ) )
  );
  return output.join(' ');
}

console.log( getOrder("milkshakepizzachickenfriescokeburgerpizzasandwichmilkshakepizza") )

  1. 创建一个包含输入字符串中存在的所有匹配项的数组
  2. 将数组中所有项的首字母转为大写,使其与菜单数组中的项完全匹配。
  3. 根据项目在菜单数组中的顺序对项目进行排序。
  4. Return数组连接成字符串

function getOrder(input) {
    
  let menu = ['Burger','Fries','Chicken','Pizza','Sandwich','Onionrings','Milkshake','Coke'];
  let items = input.match(/(burger|fries|chicken|pizza|sandwich|onionrings|milkshake|coke)/gi);
  items = items.map((element) => element.charAt(0).toUpperCase() + element.slice(1));
  items = items.sort((a, b) => {
    if (menu.indexOf(a) > menu.indexOf(b)) {
      return 1;
    }
    else {
      return -1;
    }
  });
  return items.join(" ");
}

console.log(getOrder("milkshakepizzachickenfriescokeburgerpizzasandwichmilkshakepizza"));