Search code examples
javascriptlodash

"pickBy" the value in the value array of an object


I have an object that looks like:

let documents = {"A": [{"document":"test1", "serial":"123"}, {"document":"test2", "serial":"456N"}], "B": [{"document":"test3", "serial":"789N"}, {"document":"test24, "serial":"012"}]};

I was trying to get a filtered object that has serial number ending with "N":

{"A": [{"document":"test2", "serial":"456N"}, "B": [{"document":"test3", "serial":"789N"}]}

I was doing:

 let result = _.pickBy(documents, (docObjs, client) => {
       return _.filter(docObjs, ({serial}) => {
         return _.endsWith(serial, 'N');
       });
 });

But what I got was the original object (same as documents). Is there anything wrong?


Solution

  • Lodash

    Iterate the client's object with _.transform(). For each client, filter the list of documents using _.endsWith(). If the list of documents is not empty (length 0), assign the client with filtered docs list to the result object:

    // added client C that will be filtered out
    const documents = {"A": [{"document":"test1", "serial":"123"}, {"document":"test2", "serial":"456N"}], "B": [{"document":"test3", "serial":"789N"}, {"document":"test24", "serial":"012"}], "C": [{"document":"test25", "serial":"013"}]};
    
    const result = _.transform(documents, (r, v, k) => {
      const docs = _.filter(v, ({ serial }) => _.endsWith(serial, 'N'));
      if(!_.isEmpty(docs)) r[k] = docs;
    });
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

    Vanilla JS

    Get an array of client/document pairs with Object.entries(). Using Array.map() and Array.filter() remove all documents with serials that don't String.endsWith() the letter N. Use Array.filter() to remove all entries with 0 documents. Convert back to an object using Array.reduce():

    // added client C that will be filtered out
    const documents = {"A": [{"document":"test1", "serial":"123"}, {"document":"test2", "serial":"456N"}], "B": [{"document":"test3", "serial":"789N"}, {"document":"test24", "serial":"012"}], "C": [{"document":"test25", "serial":"013"}]};
    
    const result = Object.entries(documents)
      // filter the least of documents in each client entry
      .map(([k, v]) => [k, v.filter(({ serial }) => serial.endsWith('N'))])
      // filter clients that have 0 documents
      .filter(([k, v]) => v.length)
      // convert back to an object
      .reduce((r, [k, v]) => (r[k] = v, r), {});
    
    console.log(result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>