最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Search in Array of objects on multiple values - Stack Overflow

programmeradmin3浏览0评论

I have array of objects:

[
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  },
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  },
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  }
]

I have a search bar on top and want to search for any matching string from any key which I provide. For example: I want to search from caseNumber, patientName & reader so I will call my filter function as filter(allCases, caseNumber, patientName, reader) I tried using Angular pipers but it is just working for first two keys.

I tried below code:

this.activeCases = this.filterPipe.transform(
      activeCases,
      this.searchUser,
      this.isCurrentUserTech ? 'readerName' : 'techName',
      'patientFullName',
      'caseNumber'
    );

And my pipe function:

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
  transform(items: any[], value: string, label: string, optionalLabel?: string, optionalLabel2?: string, optionalValue?: string): any[] {
    if (!items) {
      return [];
    }
    if (!optionalValue && !value) {
      return items;
    }

    if ((value === '' || value == null) && (optionalValue === '' || optionalValue == null)) {
      return [];
    }

    if (optionalValue && optionalLabel) {
      this.filterByValue(value, items, label, optionalLabel, optionalValue);
    } else if (optionalLabel) {
      return items.filter(e => (e[optionalLabel] + ', ' + e[label]).toLowerCase().indexOf(value.toLowerCase()) > -1);
    } else if (optionalLabel && label && value) {
      return items.filter(item => {
        let object: any = { item1: optionalLabel, item2: label };
        if (optionalLabel2) {
          object = { item1: optionalLabel, item2: label, item3: optionalLabel2 };
        }
        for (const property in object) {
          if (item[object[property]] === null) {
            continue;
          }
          if (item[object[property]].toString().toLowerCase().includes(value.toLowerCase())) {
            return true;
          }
        }
        return false;
      });
    } else {
      return items.filter(e => {
        const tempValue = e[label] ? e[label].toLowerCase() : '';
        return tempValue.indexOf(value.toLowerCase()) > -1;
      });
    }
  }

  filterByValue(value, items, label, optionalLabel, optionalValue) {
    if (value) {
      return items.filter(e => {
        const firstLabel = e[label] ? e[label].toLowerCase() : '';
        const secondLabel = e[optionalLabel] ? e[optionalLabel].toLowerCase() : '';
        const firstValue = value ? value.toLowerCase() : value;
        const secondValue = optionalValue ? optionalValue.toLowerCase() : optionalValue;
        let firstCheck = false;
        let secondCheck = false;
        if (firstLabel && firstValue) {
          firstCheck = firstLabel.includes(firstValue);
        }
        if (secondLabel && secondValue) {
          secondCheck = secondLabel.includes(secondValue);
        }
        return firstCheck && secondCheck;
      });
    } else {
      return items.filter(e => {
        const tempValue = e[optionalLabel] ? e[optionalLabel].toLowerCase() : '';
        return tempValue.indexOf(optionalValue.toLowerCase()) > -1;
      });
    }
  }
}

What am I missing? I can also use lodash

I have array of objects:

[
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  },
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  },
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  }
]

I have a search bar on top and want to search for any matching string from any key which I provide. For example: I want to search from caseNumber, patientName & reader so I will call my filter function as filter(allCases, caseNumber, patientName, reader) I tried using Angular pipers but it is just working for first two keys.

I tried below code:

this.activeCases = this.filterPipe.transform(
      activeCases,
      this.searchUser,
      this.isCurrentUserTech ? 'readerName' : 'techName',
      'patientFullName',
      'caseNumber'
    );

And my pipe function:

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
  transform(items: any[], value: string, label: string, optionalLabel?: string, optionalLabel2?: string, optionalValue?: string): any[] {
    if (!items) {
      return [];
    }
    if (!optionalValue && !value) {
      return items;
    }

    if ((value === '' || value == null) && (optionalValue === '' || optionalValue == null)) {
      return [];
    }

    if (optionalValue && optionalLabel) {
      this.filterByValue(value, items, label, optionalLabel, optionalValue);
    } else if (optionalLabel) {
      return items.filter(e => (e[optionalLabel] + ', ' + e[label]).toLowerCase().indexOf(value.toLowerCase()) > -1);
    } else if (optionalLabel && label && value) {
      return items.filter(item => {
        let object: any = { item1: optionalLabel, item2: label };
        if (optionalLabel2) {
          object = { item1: optionalLabel, item2: label, item3: optionalLabel2 };
        }
        for (const property in object) {
          if (item[object[property]] === null) {
            continue;
          }
          if (item[object[property]].toString().toLowerCase().includes(value.toLowerCase())) {
            return true;
          }
        }
        return false;
      });
    } else {
      return items.filter(e => {
        const tempValue = e[label] ? e[label].toLowerCase() : '';
        return tempValue.indexOf(value.toLowerCase()) > -1;
      });
    }
  }

  filterByValue(value, items, label, optionalLabel, optionalValue) {
    if (value) {
      return items.filter(e => {
        const firstLabel = e[label] ? e[label].toLowerCase() : '';
        const secondLabel = e[optionalLabel] ? e[optionalLabel].toLowerCase() : '';
        const firstValue = value ? value.toLowerCase() : value;
        const secondValue = optionalValue ? optionalValue.toLowerCase() : optionalValue;
        let firstCheck = false;
        let secondCheck = false;
        if (firstLabel && firstValue) {
          firstCheck = firstLabel.includes(firstValue);
        }
        if (secondLabel && secondValue) {
          secondCheck = secondLabel.includes(secondValue);
        }
        return firstCheck && secondCheck;
      });
    } else {
      return items.filter(e => {
        const tempValue = e[optionalLabel] ? e[optionalLabel].toLowerCase() : '';
        return tempValue.indexOf(optionalValue.toLowerCase()) > -1;
      });
    }
  }
}

What am I missing? I can also use lodash

Share Improve this question asked Jun 18, 2021 at 11:51 Faizan SaiyedFaizan Saiyed 8523 gold badges19 silver badges38 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 3

const data = [{
    caseNumber: 123,
    patientName: 'Adam',
    technician: 'Jasicca',
    reader: 'Potter',
  },
  {
    caseNumber: 456,
    patientName: 'John Doe',
    technician: 'Kevin',
    reader: 'Harry',
  },
  {
    caseNumber: 789,
    patientName: 'Ram',
    technician: 'Bob',
    reader: 'Jade Boe',
  },
];

const input = document.querySelector('input');
const log = document.getElementById('log');

function searchArray(e) {
  let filtered = [];
  const input = e.target.value.toLowerCase();
  if (input) {
    filtered = data.filter((el) => {
      return Object.values(el).some((val) =>
        String(val).toLowerCase().includes(input)
      );
    });

    log.textContent = JSON.stringify(filtered);
  }
}
<input placeholder="Enter some text" name="name" onkeyup="searchArray(event)" />
<p id="log"></p>

You could use a search object, for example { patientName: 'John', technician: 'Jasmin' } and supply it to a findResults function.

We'd use Array.filter and Array.every to ensure all search criteria are met.

If you want results to show for any search criteron, you could use Array.some instead of Array.every.

Something like:

let arr = [
  {
    "caseNumber": 123,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  },
  {
    "caseNumber": 456,
    "patientName": "John Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  },
  {
    "caseNumber": 789,
    "patientName": "Jim Doe",
    "technician": "Jasmin Joe",
    "reader": "Jade Boe"
  }
];

// Customize as appropriate.
// Currently performs a case-insensitive match
function searchMatch(target, search) {
    search = String(search).trim().toLowerCase();
    return String(target).toLowerCase().includes(search);
}

function findResults(arr, searchObj) {
    return arr.filter(el => { 
        return Object.entries(searchObj).every(([key, value]) => searchMatch(el[key], value));
    })
}

console.log("Result 1:", findResults(arr, { patientName: 'JIM'}));
console.log("Result 2:", findResults(arr, { patientName: 'John Doe'}));
console.log("Result 3:", findResults(arr, { patientName: 'jim doe', technician: 'jasmin'}));
console.log("Result 4:", findResults(arr, { caseNumber: '123' }));
console.log("Result 5:", findResults(arr, { technician: 'Mark Johnson' }));

 

发布评论

评论列表(0)

  1. 暂无评论