npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

floppy-filter

v1.0.17

Published

Just another library to filter JavaScript objects, based on a simple and flexible pattern with support for negation

Downloads

4,812

Readme

Floppy Filter

Just another library to filter JavaScript objects, based on a simple and flexible pattern with support for negation.

Node Version npm version Build Status coverage status License

Installation

npm install floppy-filter --save

Features

  • Wildcard Matching: * can be used with . to select different paths within an object.
  • Negation: ! can be used with * to allow all properties except negated paths within an object.
  • Explicit: Selecting user.address does not show address object and its nested properties but user.address.city will select address object with city property, or user.address.* to select address object and all its primitive properties

Primitive Properties: Properties with values that are not Objects

Usage

We will use this sample object to apply library functionalities

  const user = {
    "_id": "5f13c2e046d4e1b898cd25c5",
    "index": 0,
    "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
    "isActive": true,
    "balance": "$3,848.78",
    "picture": "http://placehold.it/32x32",
    "age": 35,
    "eyeColor": "blue",
    "name": {
      "first": "Callahan",
      "last": "Gilliam"
    },
    "address": {
      "country": "Philippines",
      "city": "Baliuag Nuevo",
      "street": "82 Roxbury Drive",
      "location": {
        "lat": 13.5201065,
        "lng": 123.1985807
      }
    },
    "company": "OLYMPIX",
    "email": "[email protected]",
    "phone": "+1 (845) 441-3694",
    "about": "Ullamco irure est dolor non culpa consequat.",
    "registered": "Sunday, March 15, 2015 2:07 AM",
    "latitude": "-14.770193",
    "longitude": "54.884539",
    "tags": ["ullamco", "amet", "enim", "id", "fugiat"],
    "range": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    "friends": [
      {
        "id": 0,
        "name": "Corine Mcleod"
      },
      {
        "id": 1,
        "name": "Lauri Fields"
      },
      {
        "id": 2,
        "name": "Jami Cortez"
      }
    ],
    "greeting": "Hello, Callahan! You have 8 unread messages.",
    "favoriteFruit": "apple"
  }

Select Subset

Select one or more properties

filterObject(user, ['_id', 'guid']);
// Output
{
  "_id": "5f13c2e046d4e1b898cd25c5",
  "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923"
}

Select from nested properties

filterObject(user, ['_id', 'guid', 'address.city']);
// Output
{
  "_id": "5f13c2e046d4e1b898cd25c5",
  "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
  "address": {
    "city": "Baliuag Nuevo"
  }
}

We can select all nested properties using * operator, But this will only select first level of address object which contains only (country, city, street) properties, but not the location attribute as its an object not primitive.

Here is an example:

filterObject(user, ['_id', 'guid', 'address.*']);
// Output
{
  "_id": "5f13c2e046d4e1b898cd25c5",
  "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
  "address": {
    "country": "Philippines",
    "city": "Baliuag Nuevo",
    "street": "82 Roxbury Drive"
  }
}

To select all nested properties (including objects) in address object, We need to use ** which will select all nested paths inside object

filterObject(user, ['_id', 'guid', 'address.**']);
// Output
{
  "_id": "5f13c2e046d4e1b898cd25c5",
  "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
  "address": {
    "country": "Philippines",
    "city": "Baliuag Nuevo",
    "street": "82 Roxbury Drive",
    "location": {
      "lat": 13.5201065,
      "lng": 123.1985807
    }
  }
}

Select Subset from an Array

We can select at a specific index of an array using

  • array.i.attr Select specific properties within specific item, Ex user.friends.0.id
  • array.i.* Select whole item primitive properties (Without Objects) , Ex user.friends.0.*
  • array.i.** Select whole item wit all nested properties, Ex user.friends.0.**

Using array.0 will not return the item at index 0 You must explicitly select specific attribute like friends.0.id , select all using * like friends.0.* or friends.0.**

filterObject(user, ['_id', 'guid', 'friends.0.id']);
// Output
{
  "_id": "5f13c2e046d4e1b898cd25c5",
  "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
  "friends": [
    {
      "id": 0
    }
  ]
}

filterObject(user, ['_id', 'guid', 'friends.0.*']);
// Output
{
  "_id": "5f13c2e046d4e1b898cd25c5",
  "guid": "674cd798-87a8-44e7-9be1-d4ad9c50a923",
  "friends": [
    {
      "id": 0,
      "name": "Corine Mcleod"
    }
  ]
}

Negation

Select all properties, without _id and guid properties

filterObject(user, ['*', '!_id', '!guid']);
// Output
{
    "index": 0,
    "isActive": true,
    "balance": "$3,848.78",
    "picture": "http://placehold.it/32x32",
    ...  
}

Select all properties, without address.country property

filterObject(user, ['*', '!address.country']);
// Output
{
    ...,
    "address": {
      "city": "Baliuag Nuevo",
      "street": "82 Roxbury Drive",
      "location": {
        "lat": 13.5201065,
        "lng": 123.1985807
      }
    },
    ...
}

Filter object with negation like ['*', '!address'] to filter out address object will not work, you should explicitly specify inside address object, like using:

  • ['*', '!address.country'] to filter out country property
  • ['*', '!address.*'] to filter out all primitive properties (country, city, street)
  • ['*', '!address.**'] to filter out the whole address object

Select all properties, but filter out id property from first object inside friends array

filterObject(user, ['*', '!friends.0.id']);
// Output
{
    ...,
    "friends": [
      {
        "name": "Corine Mcleod"
      },
      {
        "id": 1,
        "name": "Lauri Fields"
      },
      {
        "id": 2,
        "name": "Jami Cortez"
      }
    ],
    ...  
}

Select all properties, but filter out id property from all nested objects inside friends array

filterObject(user, ['*', '!friends.*.id']);
// Output
{
    ...,
    "friends": [
      {
        "name": "Corine Mcleod"
      },
      {
        "name": "Lauri Fields"
      },
      {
        "name": "Jami Cortez"
      }
    ],
    ...  
}

Select all properties, but filter out first object inside friends array

filterObject(user, ['*', '!friends.0.*']);
// Output
{
    ...,
    "friends": [
      {
        "id": 1,
        "name": "Lauri Fields"
      },
      {
        "id": 2,
        "name": "Jami Cortez"
      }
    ],
    ...  
}

Interesting use cases

Combining *, selection patterns and negation patterns makes it very flexible to filter JavaScript objects

You can select all primitive properties using these filters ['*', '!**.**']

const user = {
    "name": "John",
    "age": 24,
    "address": {
      "country": "Indonesia",
      "city": "Gombong",
      "street": "81 Upham Lane",
      "location": {
        "lat": -7.6052823,
        "lng": 109.5151561
      }
    },
    "phones": ["+1 (881) 402-2942", "+1 (881) 402-2946"]
};

const filter = ['*', '!**.**'];
const result = filterObject(user, filter);

console.log(result);

The result:

{
    "name": "John",
    "age": 24
}

Or do the opposite and select only objects and ignore primitive properties using these filters ['*', '!*']

and the result will be:

{
    "address": {
      "country": "Indonesia",
      "city": "Gombong",
      "street": "81 Upham Lane",
      "location": {
        "lat": -7.6052823,
        "lng": 109.5151561
      }
    },
    "phones": ["+1 (881) 402-2942", "+1 (881) 402-2946"]
}

Patterns

| Pattern (Sample) | Description | |----------------------|-----------------| | * | Select all properties in object, including all nested object, arrays (All depth levels, clone original object) | | user.* | Inside user object, select all primitive properties (No Objects) | | user.*.name | Inside user object, select "name" property within nested objects (first depth level) | | user.** | Inside user object, select all nested objects and arrays (All depth levels) | | user.**.name | Inside user object, select all objects with "name" property (All depth levels) | | *.name | Select all objects with "name" property (first depth level) within root object | | **.name | Select all objects with "name" property in all nested objects (All depth levels) within root object |

All previous patterns can be used with negation operator !

License MIT