Лучший способ разработать и сгенерировать уникальные строки из массива объектов для сопоставления

#javascript #typescript #design-patterns #anti-patterns #architectural-patterns

Вопрос:

Проблема, которую я пытаюсь решить, заключается в том, как лучше всего сгенерировать уникальную строку из набора строк вопросов/ответов.

Допустим, конечный пользователь заполняет анкету и отвечает на следующие вопросы:

    [
       {
           "is there a problem": "yes"
       },
       {
           "what is it?": "product is damaged"
       },
       {
           "do you want a refund?": "yes"
       }
   ]
 

Мне нужно сгенерировать строку, представляющую эти вопросы и ответы, а затем сопоставить ее с идентификатором шаблона, чтобы отправить шаблонное сообщение.

Я думал о том, чтобы просто запустить предварительный просмотр и добавить все вопросы и ответы вместе, но проблема в том, что, если вопросы и ответы изменятся или будут добавлены дополнительные вопросы, которые нас не интересуют для отправки сообщений.

Должен ли я вместо этого использовать что-то вроде поиска или поиска в хэш-таблице, чтобы я выбирал только те вопросы, которые мне нужны. Я тоже немного беспокоюсь о производительности, но это не должно иметь большого значения, так как этот набор вопросов/ответов должен оставаться относительно небольшим.

Мне также было интересно узнать об этом сопоставлении string -> templateId, как лучше всего хранить эту информацию, простой объект отлично работает?

Осветление:

Он не обязательно должен быть уникальным или представлять собой хэш-карту. В основном у нас есть шаблоны электронной почты в бэкэнде для отправки сообщений. Во внешнем интерфейсе нам нужно выяснить, какой шаблон электронной почты использовать, учитывая набор ответов на вопросы. Поэтому моим простым решением было добавить вопросы/ответы вместе, чтобы сгенерировать строку, то есть "isThereProblemYesWhatisIt?ProductDamagedDoyouwantaRefund?Yes"

т. е. Доступные шаблоны в бэкэнде:

 productDamaged
productLost
 

Отображение, созданное в интерфейсе.

 "isThereProblem?YesWhatisIt?ProductDamagedDoyouwantaRefund?Yes" : 
"productDamaged"
 

Спасибо

Комментарии:

1. Лучший по мнению кого/чего?

2. » что делать, если вопросы и ответы изменятся или будут добавлены дополнительные вопросы » — ну, что вы хотите сделать в этом случае? Должна ли «уникальная строка» измениться или нет? Как вы определяете, какие вопросы имеют отношение к выбору шаблона электронной почты, а какие нет?

3. Хэш — таблица здесь не кажется хорошим решением-она работает только в том случае, если вы можете перечислить все возможные входные данные. Если вы когда-нибудь добавите свободное текстовое поле в свой вопросник, это взорвется. Вместо этого напишите функцию , которая получает значения формы и возвращает строку для выбора шаблона электронной почты. Затем поместите в эту функцию любой алгоритм, который вы хотите, например, проверьте ответ на вопрос «в чем проблема «.

4. @Bergi нет возможности ввода свободного текста в анкету. Вопросы/ответы могут измениться, но затем нам придется вручную обновить сопоставление customStringGenerated -> templateId. В настоящее время у нас есть доступ к массиву вопросов/ответов. Вы предлагаете мне взять этот массив в функцию и выполнить некоторую условную логику для выбранных вопросов, а затем сгенерировать идентификатор шаблона? В этом случае мне даже не нужно другое сопоставление для stringGenerated->templateId. Я просто чувствую, что эта функция потребует тонны условной логики, хотя и это не так просто. Спасибо

5. @motime545 Да, вам всегда придется обновлять таблицу вручную. Если вы используете функцию, она просто вернет соответствующее резервное значение или выберет шаблон каким-либо другим способом. Да, для этого нужна тонна условной бизнес — логики. Начните с малого. Сохраните интерфейс функции. Если функция становится слишком сложной, выполните рефакторинг. Если у вас есть if / else цепочка или switch оператор, который проверяет конкретный вопрос, используйте для этого таблицу поиска, но обрабатывайте случаи, когда вопрос не был задан или ответа нет в таблице. Функция обеспечивает всю необходимую гибкость.

Ответ №1:

С небольшим набором вопросов и ответов перечисление выполнимо и доступно для обслуживания. Что-то вроде этого:

 const userSubmission = [{
    "is there a problem": "yes"
  },
  {
    "what is it?": "product is damaged"
  },
  {
    "do you want a refund?": "yes"
  }
]

const userSubmission2 = [{
    "is there a problem": "yes"
  },
  {
    "what is it?": "product is damaged"
  },
  {
    "do you want a refund?": "no"
  }
]

const templates = {
  "is there a problem-yeswhat is it?-product is damageddo you want a refund?-yes": "templateForDamagedAndRefundWanted",
  "is there a problem-yeswhat is it?-product is damageddo you want a refund?-no": "templateForDamagedAndRefundNotWanted"
}

function keyFromSubmission(submission) {
  return submission.reduce((acc, obj) => {
    let [key, value] = Object.entries(obj)[0]
    acc  = `${key}-${value}`
    return acc
  }, "")
}


const key = keyFromSubmission(userSubmission)
console.log(templates[key])

console.log("nOr, with a different user submission...")
const key2 = keyFromSubmission(userSubmission2)
console.log(templates[key2]) 

Редактировать

Вы можете планировать текстовые изменения в вопросах и ответах, добавив уровень косвенности. При этом вопросы, ответы и их варианты представлены символически.

 const questions = [{
    questionId: "q1",
    text: "what is the problem?",
    answers: [{
      answerId: "a1",
      text: "product was broken"
    }, {
      answerId: "a2",
      text: "product didn't arrive"
    }]
  },
  {
    questionId: "q2",
    text: "do you want a refund?",
    answers: [{
      answerId: "a1",
      text: "yes"
    }, {
      answerId: "a2",
      text: "no"
    }]
  }
]

const userSubmission = [{
    "what is the problem?": "product didn't arrive"
  },
  {
    "do you want a refund?": "yes"
  }
]

function userSubmissionAsSymbols(submission) {
  return submission.map(s => {
    let [key, value] = Object.entries(s)[0]
    let question = questions.find(q => q.text === key)
    let answer = question.answers.find(a => a.text === value)
    return `${question.questionId}-${answer.answerId}`
  })
}

console.log(userSubmissionAsSymbols(userSubmission)) 

При этом вы делаете то же самое, что и раньше, сопоставляя ключи, полученные из значений вопросов и ответов, с шаблонами. Однако в этой версии текст, представленный пользователю, может быть изменен произвольно.

Комментарии:

1. Спасибо, я думаю, что у меня было что-то подобное в голове с моим решением, и я склоняюсь к этому. Проблема, которая меня беспокоила, заключалась в необходимости вручную обновлять отображение, если вопросы/ответы все равно были изменены. Из того, что я понимаю, нам это не нужно, но вот почему я подумал о том, чтобы, возможно, использовать функцию для ручного выбора определенных вопросов из ответов, а затем генерировать строку.

2. @motime545, независимость от текста может быть достигнута косвенным путем. См.правку.

3. Спасибо, да, я подумывал об использовании функции поиска, но подумал, что у нее могут возникнуть некоторые проблемы с производительностью. Как вы думаете, безопасно ли сейчас использовать самое простое решение, т. Е. Просто создать строку, объединив вопросы/ответы, а затем переработать ее позже, чтобы использовать больше логики/найти, есть ли у вопросов/ответов более высокая вероятность изменения? Спасибо

4. Да, я думаю, что простой подход прекрасно подойдет даже для сотен вопросов и ответов.

Ответ №2:

Из вашего обновленного ответа вам следует взглянуть на условный рендеринг react, который очень похож на то, что вы хотите завершить.

На вашем интерфейсе вы должны сопоставлять каждый вопрос с индексом в массиве, например.

 ["is there a problem", "what is it?", "do you want a refund?"]
 

Таким образом, вы будете знать, что индекс 0 результатов ВСЕГДА будет «есть ли проблема», а затем вы сможете отправить чистую информацию на серверную часть, где вы сможете понять, где все как:

 ["yes", "product is damaged", "yes"]
 

В вашем бэкэнде вы сможете запускать операторы switch или операторы if. Это полностью зависит от вас, но это будет выглядеть так:

 if(data[0] === "yes" amp;amp; data[1] === "product is damaged") {
   //return email template 1
}
else if(data[0] === "yes" amp;amp; data[1] === "product is lost") {
   //return email template 2
}
 

Комментарии:

1. Вставил уточнение в исходный вопрос. Спасибо

2. Поэтому я хочу кое-что прояснить. Допустим, это единственные три вопроса, являются ли они списком ответов ИЛИ закрытыми вопросами, на которые вы знаете все возможные ответы? Второй вопрос заключается в том, повлияют ли ответы на шаблон, т. Е. существует ли фактор количества вопросов, количество шаблонов? Я думаю, что вы могли бы использовать оператор switch или оператор if, если не слишком много шаблонов. Пример, который, я думаю, вы могли бы найти похожим на вашу проблему, — это условный рендеринг react. Существуют различные «представления», которые вы можете отображать в зависимости от конкретных условий, которые очень похожи на ваши шаблоны.

3. Да, мы знаем все возможные ответы. Ответы на эти вопросы определяют, какой шаблон мы будем использовать. Сейчас у нас не так много шаблонов, но они могут вырасти. На самом деле я мог бы добавить еще одну строку в сопоставление, т. е. questionResonsesString: templateId : Причина контакта Эта причина контакта может быть чем-то, что шаблон может принять в виде текста и отобразить. По сути, нам вручную нужно сопоставить строку questionResponses с идентификатором шаблона, а также добавить reasonForContact. Я чувствовал, что на данный момент это хорошее и простое решение.

4. Хорошо, я обновил свой ответ теперь, когда я полностью понимаю вашу проблему, и это должно решить проблему, с которой вы столкнулись. Дай мне знать. 🙂

5. Спасибо за ответ. Причина, по которой я не хочу хранить эту логику в бэкэнде, заключается в том, что она специфична для конкретного клиента. Некоторые другие клиенты могут использовать эти шаблоны по другим причинам, поэтому мы хотим сохранить логику того, какой шаблон использовать на стороне клиента.