多字段过滤算法

前言

说起过滤是非常常见的业务,一般过滤推荐是服务端处理,发送请求进行模糊查询 这种情况一下,服务端返回的是每条数据中的某一个字段符合条件的数据集合

如果是前端要处理这个情况呢,前端处理过滤如果只是对于某个字段符合其中的条件很好处理,就像服务端一样,但是如果是多个字段的条件都要满足来处理的话,那就只能实现一个通用的方法来处理了

代码

单条件过滤查询

表示页面用一个输入框来搜索列表中的所有会匹配的内容,没有指定字段


export const searchBlurIgnoreCase = (
  str1: string,
  str2: string
): boolean => {
  return data.toLocaleLowerCase().indexOf(val.toLocaleLowerCase()) >= 0;
};

//统一过滤查询
export const filterDataBySearch = function (
  sourceData: Array<any>, //原始过滤数组数据
  keys: Array<string>, //需要进行过滤的字段的数组集合
  target: string //用于过滤的值
) {
  if (!target) return sourceData;
  //使用源数据进行过滤  交给过滤
  const result = sourceData.filter((data) => {
    //通过存储每条数据每个要过滤的字段的情况,收集成布尔值数组
    const flags: boolean[] = [];
    keys.forEach((key) => {
      if (!data[key]) {
         //空数据判断
        flags.push(false);
      } else {
        const res = searchBlurIgnoreCase(data[key], target);
        flags.push(res);
      }
    });
    return flags.includes(true);
  });
  return result; //交给filterData
};

多条件多字段过滤查询

需要满足多个字段的条件的过滤查询,同时筛选出满足这些条件的数据,在服务端给的数据列表中,也是当时列表没有使用分页器去写的一个算法实现,但是现在想想列表没有分页器是真的很离谱,所以现在过滤都是服务端处理的,现在看一下代码实现

export const searchBlurIgnoreCase = (
  str1: string,
  str2: string
): boolean => {
  return data.toLocaleLowerCase().indexOf(val.toLocaleLowerCase()) >= 0;
};

/**
 * 多字段过滤查询
 * @param filterData 过滤目标数组
 * @param sourceData 源数组
 * @param filterManager 需要过滤的键管理对象,该对象用于存储过滤的键名和值
 * @param filedMap 过滤键名对应过滤数组的字段名
 */

interface KeyBooleanArrayType {
  [propsName: string]: boolean[];
}

export const multiFiledFilter = () => {
  function handleDataFilter(
    filterData: any[],
    sourceData: any[],
    filterManager: object,
    filedMap: object
  ) {
    const keys = Object.keys(filterManager);
    //过滤掉没有值的键名
    const res = keys.filter((key) => {
      return filterManager[key] !== "";
    });
    if (!res.length) return clearDataFilter(filterData,sourceData,filterManager);
    const flags: KeyBooleanArrayType[] = [];
    res.forEach((key, i) => {
        //数据到达最后一个时,返回结果
      if (i === res.length - 1) {
        //只有一个字段要查询
        if (res.length === 1) {
          filterData = sourceData.filter((item) => {
            return item[filedMap[key]] && searchBlurIgnoreCase(
              item[filedMap[key]],
              filterManager[key]
            );
          });
        } else {
          //到最后一个索引时进行过滤整合处理
          filterData = sourceData.filter((item, j) => {
            return (
              item[filedMap[key]] && searchBlurIgnoreCase(item[filedMap[key]], filterManager[key]) &&
              getArrayIndexSameLevelVal(flags, j)
            );
          });
        }
        return;
      }

      //源数据进行遍历
      sourceData.forEach((item, i) => {
        //处理当前过滤的结果返回布尔值
        const res = item[filedMap[key]] && searchBlurIgnoreCase(
          item[filedMap[key]],
          filterManager[key]
        );
        //建立以属性名为key,以布尔数组为值
        if (i === 0) {
          flags.push({
            [key]: [res],
          });
        } else {
          flags.forEach((flagObj) => {
            if (flagObj[key]) {
              flagObj[key].push(res);
            }
          });
        }
      });
    });
    return filterData
  }

  function getArrayIndexSameLevelVal(
    arr: KeyBooleanArrayType[],
    index: number
  ) {
    const res: boolean[] = [];
    const keys: string[] = arr.map((flagObj) => Object.keys(flagObj)[0]);
    arr.forEach((flagObj, i) => {
      const key = keys[i]!;
      flagObj[key].forEach((b, j) => {
        if (j === index) {
          res.push(b);
        }
      });
    });
    return res.every((item) => item);
  }

  function clearDataFilter(
    filterData: any[],
    sourceData: any[],
    filterManager: object
  ) {
    for (const key in filterManager) {
      if (Object.prototype.hasOwnProperty.call(filterManager, key)) {
        filterManager[key] = "";
      }
    }
    filterData = [...sourceData];

    return filterData
  }

  return {
    handleDataFilter,
    clearDataFilter,
  };
};
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值