You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将带标签的搜索文本解析为有序数组并转换为前端组件?

Parsing Ordered Tag-Based Search Queries into Structured Arrays

My Goal

I'm building a search input where users can enter either plain text (e.g., "cats") or tag-based queries like "author:Stan cats year:1990". The end goal is to convert such queries into a component structure like:

<div>
  <Label type="author" value="Stan"/>
  <p>cats</p>
  <Label type="year" value="1990"/>
</div>

My Plan

  1. First, parse the input text (e.g., "author:Stan dogs cats year:1990") into an ordered array of objects:
[
  { type: "author", value: "stan" },
  { type: "text", value: "dogs cats" },
  { type: "year", value: "1990" }
]
  1. Then map over this array to render the correct components:
array.map(({ type, value }) => {
  if (type === 'text') {
    return <p>{value}</p>
  }
  return <Label type={type} value={value} />
})

Stuck On

I can't figure out how to parse the input into that array while keeping the original order of tags and text. Regex seems like the way to go, but I haven't been able to get it to preserve the sequence correctly.


Solution

You're right that regex is the tool for the job—you just need a pattern that matches both tag segments and plain text segments in the order they appear. Here's a step-by-step fix:

1. Build the Right Regex Pattern

We need to match two distinct types of content in sequence:

  • Tags: A tag name (letters only), followed by a colon, followed by a value (no spaces). Pattern: [a-z]+:[^\s]+
  • Plain text: One or more words separated by spaces (anything that isn't a tag). Pattern: [^\s]+(?:\s+[^\s]+)*

Combine these into a single global, case-insensitive regex that captures both groups:

const queryRegex = /([a-z]+:[^\s]+)|([^\s]+(?:\s+[^\s]+)*)/gi;

2. Parse the Query with the Regex

Use matchAll to iterate through every match, then classify each match as a tag or text and build your array:

function parseSearchQuery(input) {
  const matches = input.matchAll(queryRegex);
  const parsedResults = [];

  for (const [fullMatch, tagMatch, textMatch] of matches) {
    if (tagMatch) {
      // Split the tag into type and value
      const [type, value] = tagMatch.split(':');
      parsedResults.push({
        type: type.toLowerCase(),
        value: value.trim()
      });
    } else if (textMatch) {
      // Clean up whitespace and add as text
      const cleanedText = textMatch.trim();
      if (cleanedText) {
        parsedResults.push({
          type: 'text',
          value: cleanedText
        });
      }
    }
  }

  return parsedResults;
}

3. Test It Out

Let's run your example input through this function:

const testQuery = "author:Stan dogs cats year:1990";
console.log(parseSearchQuery(testQuery));
// Output:
// [
//   { type: 'author', value: 'Stan' },
//   { type: 'text', value: 'dogs cats' },
//   { type: 'year', value: '1990' }
// ]

Why This Works

  • The regex uses the g flag to find all matches in order, so the sequence from your input is preserved exactly.
  • The i flag makes it case-insensitive, so Author:Stan or AUTHOR:STAN will parse correctly.
  • matchAll gives us access to the capture groups, so we can easily tell if a match is a tag or plain text.
  • We skip empty text segments (from leading/trailing spaces) to avoid cluttering the array with unnecessary entries.

Once you have this parsed array, your component mapping logic will work perfectly to render the elements in the right order.

内容的提问来源于stack exchange,提问作者dev_n_null

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:58:42