最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Is there any alternatives to a huge switch, with multiple cases and fallthrough in JavaScript? - Stack Overflow

programmeradmin0浏览0评论

I need to map some user generated fields to something the system I'm working on can recognize.

For this we want to provide a certain amount of freedom for users, and offer five or so options for each of our fields.

So far we have a switch which does the job, but now we have to extend the switch, and it's going to be pretty big. This is needless to say not a very dynamic way of doing it. Is there any alternatives?

function findHeader(object) {
  var title = object.toString().trim().toLowerCase()
  switch (title) {
    case 'name':
    case 'idea':
    case 'ide':
    case 'ide navn':
    case 'title':
    case 'idea name':
      title = 'name'
      break
    case 'beskrivelse':
    case 'problemet':
    case 'description':
    case 'the problem':
    case 'ide beskrivelse':
      title = 'description'
      break
    case 'ejer':
    case 'owner':
    case 'opfinder':
    case 'ide person':
    case 'idea person':
    case 'person':
      title = 'owner'
      break
    case 'duedate':
    case 'deadline':
    case 'tidsfrist':
    case 'sidste dato':
    case 'dato':
    case 'due date':
      title = 'duedate'
      break
    case 'billede':
    case 'billeder':
    case 'image':
    case 'images':
    case 'attachment':
      title = 'imageUrl'
      break
    case "":
      title = 'remove'
      break
    default:
      title = 'Unassigned'
      break
  }
  return title
}

I need to map some user generated fields to something the system I'm working on can recognize.

For this we want to provide a certain amount of freedom for users, and offer five or so options for each of our fields.

So far we have a switch which does the job, but now we have to extend the switch, and it's going to be pretty big. This is needless to say not a very dynamic way of doing it. Is there any alternatives?

function findHeader(object) {
  var title = object.toString().trim().toLowerCase()
  switch (title) {
    case 'name':
    case 'idea':
    case 'ide':
    case 'ide navn':
    case 'title':
    case 'idea name':
      title = 'name'
      break
    case 'beskrivelse':
    case 'problemet':
    case 'description':
    case 'the problem':
    case 'ide beskrivelse':
      title = 'description'
      break
    case 'ejer':
    case 'owner':
    case 'opfinder':
    case 'ide person':
    case 'idea person':
    case 'person':
      title = 'owner'
      break
    case 'duedate':
    case 'deadline':
    case 'tidsfrist':
    case 'sidste dato':
    case 'dato':
    case 'due date':
      title = 'duedate'
      break
    case 'billede':
    case 'billeder':
    case 'image':
    case 'images':
    case 'attachment':
      title = 'imageUrl'
      break
    case "":
      title = 'remove'
      break
    default:
      title = 'Unassigned'
      break
  }
  return title
}
Share Improve this question edited Dec 12, 2018 at 10:55 mplungjan 179k28 gold badges182 silver badges240 bronze badges asked Dec 12, 2018 at 10:52 Anders JensenAnders Jensen 3295 silver badges21 bronze badges 5
  • please add example for the input also – Naor Tedgi Commented Dec 12, 2018 at 10:57
  • How about this? stackoverflow./questions/35769144/… – thex Commented Dec 12, 2018 at 10:58
  • 2 You can just create a map. You can store it as a separate JSON file if it is dynamic and big. Personally, Personally for me this "certain amount of freedom" sounds more like ambiguity and confusion. Why would someone want to build a service which allows multiple different names for the same thing and creates a fishy map to handle user's invalid data for him. IMHO :) – Yeldar Kurmangaliyev Commented Dec 12, 2018 at 11:00
  • We switched to a system where the label is decoupled from the fieldname. So we offer our users only the fieldname: 'name', 'description' and such, and then let them define any label name they want as tied to the standardized name. So kinda like the opposite of your current method. The big advantage is that you don't need to hard code all the different spellings of the same concept, since the user will ad those themselves to the JSON file / database / data store. – Shilly Commented Dec 12, 2018 at 11:16
  • There is a really good article about it. – Experimenter Commented Apr 19, 2022 at 20:39
Add a ment  | 

7 Answers 7

Reset to default 6

Perhaps an object?

const titles = {
  'name':        ['name', 'idea', 'ide', 'ide navn', 'title', 'idea name'],
  'description': ['beskrivelse', 'problemet', 'description', 'the problem', 'ide beskrivelse'],
  'owner' :      ['ejer', 'owner', 'opfinder', 'ide person', 'idea person', 'person'],
  'duedate' :    ['duedate', 'deadline', 'tidsfrist', 'sidste dato', 'dato', 'due date'],
  'imageUrl' :   ['billede', 'billeder', 'image', 'images', 'attachment']
}
const getKey = (obj,val) => Object.keys(obj).find(key => obj[key].indexOf(val) !=-1 );

function findHeader(object) {  
  var title = object.toString().trim().toLowerCase();
  return getKey(titles,title) || 'Unassigned' 
}

console.log(
  findHeader("Owner"),
  findHeader("Bla")
)  

You can store datas in array of object and search values in it instead of switch

let arr = [
  {
    "title": "name",
    "values": ['idea','ide','ide navn','title','idea name']
  },
  {
    "title": "description",
    "values": ['beskrivelse','problemet','description','the problem','ide beskrivelse']
  },
  {
    "title": "owner",
    "values": ['ejer','owner','opfinder','ide person','idea person','person']
  },
];    

function findHeader(object) {
  let title = object.toString().trim().toLowerCase(),
      res = arr.filter(val => val.values.includes(title));    
  return res.length ? res[0].title : "Unassigned";
}

console.log(findHeader("problemet"));
console.log(findHeader("ide person"));
console.log(findHeader("opfinderrr"));

You can use a regular expression with an object to get the value of an item based on a string of keys:

const titles = {
  "name|idea|ide": "name",
  "beskrivelse|problemt|description|the problem": "description"
};

const get_item = item => titles[Object.keys(titles).find(key => new RegExp(`(\\||^)${item}(\\||$)`).test(key))];

let title = "problemt";
title = get_item(title); // Get the associated value from the key
console.log(title);

See this answer for further details.

The solutions others have posted are great and elegant if one expects not too much data.

If performance is crucial and you have huge dictionaries, and/or a lot of terms to replace (order of magnitude 100k or more pieces of data), then your original solution using switch and case statements will be the best one, especially if you put the assignment line and the break statement after every singe case (making it even uglier). The problem is that you cannot dynamically update that at runtime.

But if dynamic updates is not what you need, you can save this monster of a switch statement into a separate script file as a function, out of sight, keeping your code tidy.

The point is, while the use of JavaScript objects is much more elegant, I wouldn't pletely discount the switch & case solution, depending on the application.

Cleaner way to do that

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论