【问题标题】:Javascript search filter to a array?Javascript搜索过滤器到数组?
【发布时间】:2022-01-02 03:31:17
【问题描述】:

我正在构建一个nextjs 应用程序。一切正常。但在一个组件中,我面临一个问题。其实我无法理解它的功能。我有一个ArraySub-Array。我必须将search 过滤器添加到Array。当匹配一个项目或子项目时,该函数将返回。但是看不懂。。

这里是代码。

这个id数据-

export default [
    {
        name: "Top Wear",
        sub: [
            { name: "T-Shirts" },
            { name: "Casual Shirts" }
        ]
    }
    {
        name: "Western Wear",
        sub: [
            { name: "Dresses" },
            { name: "Jumpsuits" }
        ]
    },
    { name: "Plus Size" },
    { name: "Sunglasses and Frames" },
    {
        name: "Footwear",
        sub: [
            { name: "Casual Shoes" },
            { name: "Sports Shoes" }
        ]
    },
    {
        name: "Lingerie & Sleepwear",
        sub: [
            { name: "Bra" },
            { name: "Briefs" }
        ]
    },
    {
        name: "Sports & Active Wear",
        sub: [
            { name: "Sports Shoes" },
            { name: "Sports Sandals" },
            { name: "Active T-Shirts" },
            { name: "Active T-Shirts" },
        ]
    },
    {
        name: "Gadgets",
        sub: [
            { name: "Smart Wearables" },
            { name: "Fitness Gadgets" }
        ]
    },
    { name: "Bag & Backpacks" },
    { name: "Luggages & Trolleys " }
]

这里我想添加直接匹配namesub.name 的搜索功能。我不明白如何编写函数。如果只有一个 Array 没有 Sub-Array..

,我可以这样做

此代码是第一个Array 而不是Sub-Array

import { useState, useEffect } from "react";

//Data
import CategoriesData from "Data/Header/SearchBar.data";

const Categories = ({ setFilterData, filterData }) => {
    const [categories, setCategories] = useState(CategoriesData);
    const [input, setInput] = useState("");
    useEffect(() => {
        if (input.length > 0) {
            const mathches = CategoriesData.filter(item => {
                const escapeRegExp = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
                const regex = new RegExp(escapeRegExp(input), "gi");
                return item.name.match(regex);
            })
            setCategories(mathches);
        } else {
            setCategories(CategoriesData);
        }
    }, [CategoriesData, input]);
    return (
        <Box>
            <Box>
                <InputBase
                    value={input}
                    onChange={(e) => setInput(e.target.value)}
                />
            </Box>
            <List>
                {categories &&
                    categories.map((category, i) => (
                        <Box key={i}>
                            <ListItem>
                                <ButtonBase>
                                    <Typography>
                                        {category.name}
                                    </Typography>
                                </ButtonBase>
                            </ListItem>
                            {category.sub &&
                                category.sub.map((subCategory, i) => (
                                    <ListItem key={i}>
                                        <ButtonBase>
                                            <Typography>
                                                {subCategory.name}
                                            </Typography>
                                        </ButtonBase>
                                    </ListItem>
                                ))
                            }
                        </Box>
                    ))
                }
            </List>
        </Box>
    );
};

export default Categories;

请帮帮我..

【问题讨论】:

  • 是否要维护{ name: ..., sub: [ ... ] } 结构?

标签: javascript arrays reactjs filter


【解决方案1】:

这是一个递归解决方案 -- search() 在数据中保留一个匹配数组,每当遇到名为 sub 的子数组时,它会再次使用该子数组调用自身。

未实现:区分大小写、错误处理或超出匹配字符串的裸数组的有用输出。

const search = (str, data) => {
  let out = [];
  for (let obj of data) {
    if (obj.name.indexOf(str) > -1) {
      out.push(obj.name)
    }
    
    if (obj.sub) { 
      // recurse if there's a child array
      out.push(search(str, obj.sub))
    }
  }
  return out.flat()
}

output = search("e", [{
    name: "Top Wear",
    sub: [{
        name: "T-Shirts"
      },
      {
        name: "Casual Shirts"
      }
    ]
  }, {
    name: "Western Wear",
    sub: [{
        name: "Dresses"
      },
      {
        name: "Jumpsuits"
      }
    ]
  },
  {
    name: "Plus Size"
  },
  {
    name: "Sunglasses and Frames"
  },
  {
    name: "Footwear",
    sub: [{
        name: "Casual Shoes"
      },
      {
        name: "Sports Shoes"
      }
    ]
  },
  {
    name: "Lingerie & Sleepwear",
    sub: [{
        name: "Bra"
      },
      {
        name: "Briefs"
      }
    ]
  },
  {
    name: "Sports & Active Wear",
    sub: [{
        name: "Sports Shoes"
      },
      {
        name: "Sports Sandals"
      },
      {
        name: "Active T-Shirts"
      },
      {
        name: "Active T-Shirts"
      },
    ]
  },
  {
    name: "Gadgets",
    sub: [{
        name: "Smart Wearables"
      },
      {
        name: "Fitness Gadgets"
      }
    ]
  },
  {
    name: "Bag & Backpacks"
  },
  {
    name: "Luggages & Trolleys "
  }
])

console.log(output)

【讨论】:

  • 我还不清楚.. 你能帮我清除一下吗..
  • 我收到ReferenceError: assignment to undeclared variable obj 这个错误。
  • 我还不能理解。
  • 我忘了为严格的js声明'obj';添加了一个 let 应该处理该警告。
【解决方案2】:

当然,您可以进行递归搜索,但您也可以将搜索数据展平,使其没有深度,然后执行与您在代码中所做的完全相同的搜索。为了展平您的数据,您可以使用数组函数:

data.flatMap(v => v.sub).concat(data.map(({sub, ...item}) => item))

请记住,这不会改变主数据数组。

所以首先它使用flatMap 来获取sub 属性并将它们展平,所以此时你有一个子类别数组,然后将它与主要类别列表连接起来(现在只使用地图他们的子属性被删除,导致它变平)。最后,您有一个包含 28 个类别(10 个主要 + 18 个子)的数组来过滤。您可以链接 filter 方法并继续。

【讨论】:

    【解决方案3】:

    使用reduce代替过滤器。您可以同时过滤和修改子数组。使用 reduce 帮助同时操作数据和过滤。

    您可以根据需要修改逻辑。

    示例代码:

    const mathches = CategoriesData.reduce((acc, item) => {
      const escapeRegExp = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
      const regex = new RegExp(escapeRegExp(input), "gi");
      if(item.sub) {
        const sub = item.sub.filter(({name}) => name.match(regex))
        if(sub.length){
          acc.push({name: item.name, sub})
        }
      }
      else if(item.name.match(regex)){
        acc.push(item)
      }
      return acc;
    },[])
    

    示例:

    const data = [
      {
        name: "Top Wear",
        sub: [{ name: "T-Shirts" }, { name: "Casual Shirts" }],
      },
      {
        name: "Western Wear",
        sub: [{ name: "Dresses" }, { name: "Jumpsuits" }],
      },
      { name: "Plus Size" },
      { name: "Sunglasses and Frames" },
      {
        name: "Footwear",
        sub: [{ name: "Casual Shoes" }, { name: "Sports Shoes" }],
      },
      {
        name: "Lingerie & Sleepwear",
        sub: [{ name: "Bra" }, { name: "Briefs" }],
      },
      {
        name: "Sports & Active Wear",
        sub: [
          { name: "Sports Shoes" },
          { name: "Sports Sandals" },
          { name: "Active T-Shirts" },
          { name: "Active T-Shirts" },
        ],
      },
      {
        name: "Gadgets",
        sub: [{ name: "Smart Wearables" }, { name: "Fitness Gadgets" }],
      },
      { name: "Bag & Backpacks" },
      { name: "Luggages & Trolleys " },
    ];
    
    const search = (data, input) => {
      const mathches = data.reduce((acc, item) => {
        const escapeRegExp = (str) =>
          str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
        const regex = new RegExp(escapeRegExp(input), "gi");
        
        if (item.sub) {
          const sub = item.sub.filter(({ name }) => name.match(regex));
          if (sub.length) {
            acc.push({ name: item.name, sub });
          }
        } else if (item.name.match(regex)) {
          acc.push(item);
        }
    
        return acc;
      }, []);
      return mathches;
    };
    
    console.log(search(data, "Top Wear"));
    console.log(search(data, "Sandals"));
    console.log(search(data, "Shoes"));

    【讨论】:

      猜你喜欢
      • 2020-05-30
      • 2018-12-25
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 2019-04-14
      • 2015-12-21
      相关资源
      最近更新 更多