javascript - 如何通过多个标签过滤 JSON 中的数组

标签 javascript reactjs

我正在 React 中渲染来自 Json 的图像列表,如下所示

{
  "images": [
    ["c8483f65-f67f-48d9-a0f8-78da8f66115d", "Image 0", "https://cdn.shibe.online/shibes/2293625f8b5e74478e51434fbbe158b43f17b04f.jpg", ["servant", "shoes"]],
    ["4d22a5b7-079d-4f1c-9eba-570165c1f6b1", "Image 1", "https://cdn.shibe.online/shibes/4cc3559217012e477a674862f13d4ac533733cff.jpg", ["screw", "restaurant"]],
    ["acd3b528-3c56-41c9-a2bc-6094a55e21be", "Image 2", "https://cdn.shibe.online/shibes/6e817b4032beccbd7a3c93dc3b7e1f771e15aaec.jpg", ["cub", "relation"]],
    ["fca42de6-0eb1-4449-ab91-61b558c7b972", "Image 3", "https://cdn.shibe.online/shibes/d14e008e2aa18bcae592c5e16968050e7ca5ed43.jpg", ["condition", "butter"]],
    ["73fa77dd-6ec6-4f4d-a991-1bc6b59fb5fa", "Image 4", "https://cdn.shibe.online/shibes/2ca352bdf59566dbffef94724a192713f8970437.jpg", ["zoo", "wheel"]],
    ["34982d91-d537-4bc0-a481-028879a22c27", "Image 5", "https://cdn.shibe.online/shibes/6e7e3e6a60dcd4b27ac6940a8f44893010f171e4.jpg", ["way", "chess"]],
    ["4bdc55e4-937a-4208-aff3-981776a2404e", "Image 6", "https://cdn.shibe.online/shibes/20f3c14be166a24376e98b81f9464e153e6ece55.jpg", ["country", "smell"]],
{

我从 JSON 中获取此数据,并将其作为 props 传递给名为 ImageList 的 React 组件,该组件会映射并呈现它们,如下所示

class ImageList extends React.Component{
    render(){
    console.log(this.props.images)
        var mappedImages = this.props.images.map(
        (img,index) => {
            return (
            <Img className = 'img' key = {img[0]} alt = {img[1]} src = {img[2]} tags = {img[3]}/>
            );
          } 
        );

        return(
            <div className = "imageList">
                {mappedImages}

           </div>
        );
    }
}

我如何按名称和/或多个标签过滤此图像。 每个数组的第二个元素是图像的名称,最后一个元素是标签数组。

最佳答案

您可以使用Array.prototype.filter()根据您的搜索检查每个单独的图像和 Array.prototype.find()Array.prototype.some()Array.prototype.includes()检查给定图像的任何标签是否与搜索中的标签匹配:

const images = [
  ["Image 0", ["servant", "shoes"]],
  ["Image 1", ["screw", "restaurant"]],
  ["Image 2", ["cub", "relation"]],
  ["Image 3", ["condition", "butter"]],
  ["Image 4", ["zoo", "wheel"]],
  ["Image 5", ["way", "chess"]],
  ["Image 6", ["country", "smell"]],
];

const searchName = "Image 3";
const searchTags = ["cub", "country"];

console.log(images.filter(([name, tags]) => {
  // With .find:
  // return name === searchName || tags.find(tag => searchTags.includes(tag));
  
  // With .some:
  return name === searchName || tags.some(tag => searchTags.includes(tag));
}).map(image => image[0]).join(', '));

如果您需要考虑不区分大小写、忽略空格和换行符或仅考虑搜索中的更多字段等问题,您可以向这些图像添加“搜索”属性,您可能只会计算这些图像在服务中,然后使用单个 RegExp里面Array.prototype.filter() :

const images = [
  ["Image 0", ["servant", "shoes"]],
  ["Image 1", ["screw", "restaurant"]],
  ["Image 2", ["cub", "relation"]],
  ["Image 3", ["condition", "butter"]],
  ["Image 4", ["zoo", "wheel"]],
  ["Image 5", ["way", "chess"]],
  ["Image 6", ["country", "smell"]],
];

const searchName = "Image 3";
const searchTags = ["cub", "country"];

// Generate your search RegExp based on the active filters:
const searchRegExp = new RegExp(`${ searchName }|${ searchTags.join('|') }`.replace(/\s/g, '\\s'), 'i');

console.log(searchRegExp);

// You would do this in the service or in a selector, not inside render,
// so that you only compute it once:

const imagesWithSearchTerm = images.map(image => {
  const [name, tags] = image;
  
  // Concatenate all fields you want to take into account for the search:
  image.push(`${ name }, ${ tags.join(', ') }`);
  
  return image;
});

console.log(imagesWithSearchTerm.filter(image => {
  return searchRegExp.test(image[2]);
}).map(image => image[0]).join(', '));

在这个简单的示例中,RegExp 解决方案速度较慢且看起来更复杂,但如果搜索逻辑增长,这实际上可能会更快且更容易理解/推理。

此外,您的过滤逻辑不应位于 render 内部,因为这可能会给您的应用程序带来一些性能问题。您应该将其移至服务/选择器或 use memoization ,无论是在整个组件上还是仅在过滤逻辑周围。

第一个搜索解决方案和以前的内存方法看起来像这样:

const ImageList = React.memo(({
    searchName,
    searchTags,
    images,
}) => {
    const mappedImages = images.filter(([name, tags]) => {
        return name === searchName || tags.some(tag => searchTags.includes(tag));
    }).map(([name, tags, src]) => (
        <Img
            key={ name }
            className="img"
            tags={ tags }
            src={ src }
        />
    ));

    return (
        <div className="imageList">
            { mappedImages }
        </div>
    );
});

关于javascript - 如何通过多个标签过滤 JSON 中的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59144468/

相关文章:

javascript - React 重新渲染后 Zurb Foundation 6 刷新

javascript - jQuery:处理跨域jsonp错误请求错误

javascript - 将脚本标签插入 Angular 4 HTML 组件

javascript - 如何使用嵌套数组查找两个数组之间的差异

node.js - 我需要将 server.js 添加到 webpack 文件中吗?

javascript - 单击时 Bootstrap Accordion 不展开

javascript - 如何动态更改玩家ID和 key ?

javascript - 将鼠标悬停在同级上会停止悬停效果

javascript - 为什么在 react 中将数据存储在状态中

javascript - 如何将从 Promise 获得的数据存储回具有与其来源相同的 key 的对象中?