Home > other >  Is there a way to filter an array of objects with multiple dynamic conditions by another array data
Is there a way to filter an array of objects with multiple dynamic conditions by another array data

Time:06-17

I want to filters data dynamically by multiple checkbox and its own attributes, this is the main data object

[
  {
    "_id": "61f0a145c6a48a907bd102ce",
    "contract_id": "asac.near",
    "token_series_id": "9",
    "creator_id": "asac.near",
    "in_circulation": 1,
    "metadata": {
      "name": "Antisocial Ape Club #10",
      "symbol": "ASAC",
      "description": "A collection of 3333 unique, randomly generated pixel art ape NFTs stored on the NEAR blockchain.",
      "seller_fee_basis_points": 500,
      "image": "image.png",
      "external_url": "https://antisocialape.club/",
      "attributes": [
        {
          "trait_type": "Antisocial Ape Club",
          "value": "Genesis Apes",
          "rarity_score": "1.00"
        },
        {
          "trait_type": "Skin",
          "value": "Zombie",
          "rarity_score": "14.29"
        },
        {
          "trait_type": "Mouth",
          "value": "Cigarette",
          "rarity_score": "3.85"
        },
        {
          "trait_type": "Eyes",
          "value": "Golden Goggles",
          "rarity_score": "14.29"
        },
        {
          "trait_type": "Head",
          "value": "Devil Horns",
          "rarity_score": "100.00"
        },
        {
          "trait_type": "Neck",
          "value": "None",
          "rarity_score": "1.37"
        },
        {
          "trait_type": "Earrings",
          "value": "Silver Stud",
          "rarity_score": "3.33"
        }
      ],
      "properties": {
        "files": [
          {
            "uri": "image.png",
            "type": "image/png"
          }
        ],
        "category": "image",
        "creators": [
          {
            "address": "asac.near",
            "share": 100
          }
        ]
      },
      "title": "Antisocial Ape Club #10",
      "media": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/9.png",
      "media_hash": null,
      "issued_at": "1643134423232219685",
      "expires_at": null,
      "starts_at": null,
      "updated_at": null,
      "extra": null,
      "reference": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/9.json",
      "reference_hash": null,
      "creator_id": "asac.near",
      "collection": null,
      "score": 88.68721692128618
    },
    "price": null,
    "royalty": {
      "asac.near": "500"
    },
    "isMediaCdn": true,
    "collection": null,
    "lowest_price": null,
    "has_price": null,
    "total_rarity_score": 138.13,
    "rank": 1
  },
  {
    "_id": "61f0a148c6a48a907bd1065f",
    "contract_id": "asac.near",
    "token_series_id": "5",
    "creator_id": "asac.near",
    "in_circulation": 1,
    "metadata": {
      "name": "Antisocial Ape Club #6",
      "symbol": "ASAC",
      "description": "A collection of 3333 unique, randomly generated pixel art ape NFTs stored on the NEAR blockchain.",
      "seller_fee_basis_points": 500,
      "image": "image.png",
      "external_url": "https://antisocialape.club/",
      "attributes": [
        {
          "trait_type": "Antisocial Ape Club",
          "value": "Genesis Apes",
          "rarity_score": "1.00"
        },
        {
          "trait_type": "Skin",
          "value": "Green",
          "rarity_score": "20.00"
        },
        {
          "trait_type": "Mouth",
          "value": "None",
          "rarity_score": "2.70"
        },
        {
          "trait_type": "Eyes",
          "value": "None",
          "rarity_score": "2.94"
        },
        {
          "trait_type": "Head",
          "value": "Crown",
          "rarity_score": "100.00"
        },
        {
          "trait_type": "Neck",
          "value": "None",
          "rarity_score": "1.37"
        },
        {
          "trait_type": "Earrings",
          "value": "Silver Stud",
          "rarity_score": "3.33"
        }
      ],
      "properties": {
        "files": [
          {
            "uri": "image.png",
            "type": "image/png"
          }
        ],
        "category": "image",
        "creators": [
          {
            "address": "asac.near",
            "share": 100
          }
        ]
      },
      "title": "Antisocial Ape Club #6",
      "media": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/5.png",
      "media_hash": null,
      "issued_at": "1643135661510924041",
      "expires_at": null,
      "starts_at": null,
      "updated_at": null,
      "extra": null,
      "reference": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/5.json",
      "reference_hash": null,
      "creator_id": "asac.near",
      "collection": null,
      "score": 106.86118243409153
    },
    "price": null,
    "royalty": {
      "asac.near": "500"
    },
    "isMediaCdn": true,
    "collection": null,
    "lowest_price": null,
    "updated_at": 1649489685487,
    "has_price": null,
    "total_rarity_score": 131.34,
    "rank": 2
  },
  {
    "_id": "61f0a163c6a48a907bd11a77",
    "contract_id": "asac.near",
    "token_series_id": "39",
    "creator_id": "asac.near",
    "in_circulation": 1,
    "metadata": {
      "name": "Antisocial Ape Club #40",
      "symbol": "ASAC",
      "description": "A collection of 3333 unique, randomly generated pixel art ape NFTs stored on the NEAR blockchain.",
      "seller_fee_basis_points": 500,
      "image": "image.png",
      "external_url": "https://antisocialape.club/",
      "attributes": [
        {
          "trait_type": "Antisocial Ape Club",
          "value": "Genesis Apes",
          "rarity_score": "1.00"
        },
        {
          "trait_type": "Skin",
          "value": "Gingerbread",
          "rarity_score": "100.00"
        },
        {
          "trait_type": "Mouth",
          "value": "Blunt",
          "rarity_score": "3.45"
        },
        {
          "trait_type": "Eyes",
          "value": "Red Vr Headset",
          "rarity_score": "14.29"
        },
        {
          "trait_type": "Head",
          "value": "None",
          "rarity_score": "5.00"
        },
        {
          "trait_type": "Neck",
          "value": "None",
          "rarity_score": "1.37"
        },
        {
          "trait_type": "Earrings",
          "value": "Silver Stud",
          "rarity_score": "3.33"
        }
      ],
      "properties": {
        "files": [
          {
            "uri": "image.png",
            "type": "image/png"
          }
        ],
        "category": "image",
        "creators": [
          {
            "address": "asac.near",
            "share": 100
          }
        ]
      },
      "title": "Antisocial Ape Club #40",
      "media": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/39.png",
      "media_hash": null,
      "issued_at": "1643133670278506382",
      "expires_at": null,
      "starts_at": null,
      "updated_at": null,
      "extra": null,
      "reference": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/39.json",
      "reference_hash": null,
      "creator_id": "asac.near",
      "collection": null,
      "score": 132.14806994411788
    },
    "price": null,
    "royalty": {
      "asac.near": "500"
    },
    "isMediaCdn": true,
    "collection": null,
    "lowest_price": null,
    "updated_at": 1651360595494,
    "has_price": null,
    "total_rarity_score": 128.44,
    "rank": 3
  },
]

I put values from checkbox for trait_type and value on the main object in an array like this

[
    "Genesis Apes",
    "Antisocial Ape Club",
    "Zombie",
    "Skin"
]

and I made an array of keys like this

[
    "trait_type",
    "value",
]

then I use filter, every and Includes to set the value of filtered variables but it doesn't work and the result length is 0

setFilteredNftDatas(nftsDatas.filter(function (nftData: any) {
      return nftData.metadata.attributes.every(function (elem: any, index: any, array: any) {
        return filtersKeys.every(function (key) {
          return filtersValues.includes(nftData.metadata.attributes[index][key]);
        })
      })
    }));

CodePudding user response:

Not sure it totaly solves your problem but I think it can helps you :

let data = [
    {
        'param1': 'a',
        'param2': 'b',
        'param3': 'c',
    },
    {
        'param1': 'a',
        'param2': 'd',
        'param3': 'e',
    },
    {
       'param1': 'e',
        'param2': 'a',
        'param3': 'd',
    },
]

let keys = ['param1', 'param2'];
let values = ['b', 'e'];

let filtered_data = data.filter(d => {
    for(let key of keys) {
        for(let value of values) {
            if(d[key] == value) {
                return true;
            }
        }
    }
    return false;
});

console.log(filtered_data);
//Output :
[
    {param1: 'a', param2: 'b', param3: 'c'},
    {param1: 'e', param2: 'a', param3: 'd'}
]

CodePudding user response:

Try something like this, it filters all the nfts that has given attributes keys with specified values:

const data = ...your data
const keys = ["trait_type", "value"]
const values = ["Genesis Apes", "Antisocial Ape Club", "Zombie", "Skin"]

const filterData = (data, keys, values) => {
  const filteredData = data.filter(nft => {
    return nft.metadata.attributes.some(attribute => {
      return Object.keys(attribute).find(key => keys.includes(key) && values.includes(attribute[key])
      )})
    })
  
  return filteredData
}

CodePudding user response:

I use my ruleOut function for filtering objects based on specific unwanted property values.

function ruleOut(arr, filterObj, applyAllFilters=true) {    
    return arr.filter( row => {            
        for (var field in filterObj) {
            var val = row[field];
            if (val) {                    
                if (applyAllFilters && filterObj[field].indexOf(val) > -1) return false;                
                else if (!applyAllFilters) {                        
                    return filterObj[field].filter(function(filterValue){ 
                        return (val.indexOf(filterValue)>-1);
                    }).length == 0;                 
                }
            }
        }
        return true;
    });
}

Say you have a list of actors like this:

let actors = [
  {userName:"Mary", job:"star", language:"Turkish"},
  {userName:"John", job:"actor", language:"Turkish"},
  {userName:"Takis", job:"star", language:"Greek"},
  {userName:"Joe", job:"star", language:"Turkish"},
  {userName:"Bill", job:"star", language:"Turkish"}
];

and you would like to find all actors that are rated as Holywood stars, their nationality should not be one of 'English', 'Italian', 'Spanish', 'Greek', plus their name would not be one of 'Mary', 'Joe'. Bizzar example, I know! Anyway, with that set of conditions you would create the following object:

let unwantedFieldsFilter= { 
  userName: ['Mary', 'Joe'],    
  job: ['actor'],   
  language: ['English', 'Italian', 'Spanish', 'Greek']  
};

OK, now if you ruleOut(actors, unwantedFieldsFilter) you would only get

[{userName: "Bill", job: "star", language: "Turkish"}]

And Bill is your man, since his name is not one of 'Mary', 'Joe', his nationality is not included in ['English', 'Italian', 'Spanish', 'Greek'] plus he is a Star!

There is one option in my method, that is applyAllFilters and is true by default. If you would try to ruleOut with this param set as false, that would work as an 'OR' filtering instead of 'AND'. Example: ruleOut(actors, {job:["actor"], language:["Italian"]}, false) would get you everyone that is not an actor or Italian:

[{userName: "Mary", job: "star", language: "Turkish"},
{userName: "Takis", job: "star", language: "Greek"},
{userName: "Joe", job: "star", language: "Turkish"},
{userName: "Bill", job: "star", language: "Turkish"}]

CodePudding user response:

I made a decently extendable multi-way filtering code.

const data = [
  {
    "_id": "61f0a145c6a48a907bd102ce",
    "contract_id": "asac.near",
    "token_series_id": "9",
    "creator_id": "asac.near",
    "in_circulation": 1,
    "metadata": {
      "name": "Antisocial Ape Club #10",
      "symbol": "ASAC",
      "description": "A collection of 3333 unique, randomly generated pixel art ape NFTs stored on the NEAR blockchain.",
      "seller_fee_basis_points": 500,
      "image": "image.png",
      "external_url": "https://antisocialape.club/",
      "attributes": [
        {
          "trait_type": "Antisocial Ape Club",
          "value": "Genesis Apes",
          "rarity_score": "1.00"
        },
        {
          "trait_type": "Skin",
          "value": "Zombie",
          "rarity_score": "14.29"
        },
        {
          "trait_type": "Mouth",
          "value": "Cigarette",
          "rarity_score": "3.85"
        },
        {
          "trait_type": "Eyes",
          "value": "Golden Goggles",
          "rarity_score": "14.29"
        },
        {
          "trait_type": "Head",
          "value": "Devil Horns",
          "rarity_score": "100.00"
        }
      ],
      "properties": {
        "files": [
          {
            "uri": "image.png",
            "type": "image/png"
          }
        ],
        "category": "image",
        "creators": [
          {
            "address": "asac.near",
            "share": 100
          }
        ]
      },
      "title": "Antisocial Ape Club #10",
      "media": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/9.png",
      "media_hash": null,
      "issued_at": "1643134423232219685",
      "expires_at": null,
      "starts_at": null,
      "updated_at": null,
      "extra": null,
      "reference": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/9.json",
      "reference_hash": null,
      "creator_id": "asac.near",
      "collection": null,
      "score": 88.68721692128618
    },
    "price": null,
    "royalty": {
      "asac.near": "500"
    },
    "isMediaCdn": true,
    "collection": null,
    "lowest_price": null,
    "has_price": null,
    "total_rarity_score": 138.13,
    "rank": 1
  },
  {
    "_id": "61f0a148c6a48a907bd1065f",
    "contract_id": "asac.near",
    "token_series_id": "5",
    "creator_id": "asac.near",
    "in_circulation": 1,
    "metadata": {
      "name": "Antisocial Ape Club #6",
      "symbol": "ASAC",
      "description": "A collection of 3333 unique, randomly generated pixel art ape NFTs stored on the NEAR blockchain.",
      "seller_fee_basis_points": 500,
      "image": "image.png",
      "external_url": "https://antisocialape.club/",
      "attributes": [
        {
          "trait_type": "Antisocial Ape Club",
          "value": "Genesis Apes",
          "rarity_score": "1.00"
        },
        {
          "trait_type": "Skin",
          "value": "Green",
          "rarity_score": "20.00"
        },
        {
          "trait_type": "Mouth",
          "value": "None",
          "rarity_score": "2.70"
        },
        {
          "trait_type": "Neck",
          "value": "None",
          "rarity_score": "1.37"
        },
        {
          "trait_type": "Earrings",
          "value": "Silver Stud",
          "rarity_score": "3.33"
        }
      ],
      "properties": {
        "files": [
          {
            "uri": "image.png",
            "type": "image/png"
          }
        ],
        "category": "image",
        "creators": [
          {
            "address": "asac.near",
            "share": 100
          }
        ]
      },
      "title": "Antisocial Ape Club #6",
      "media": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/5.png",
      "media_hash": null,
      "issued_at": "1643135661510924041",
      "expires_at": null,
      "starts_at": null,
      "updated_at": null,
      "extra": null,
      "reference": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/5.json",
      "reference_hash": null,
      "creator_id": "asac.near",
      "collection": null,
      "score": 106.86118243409153
    },
    "price": null,
    "royalty": {
      "asac.near": "500"
    },
    "isMediaCdn": true,
    "collection": null,
    "lowest_price": null,
    "updated_at": 1649489685487,
    "has_price": null,
    "total_rarity_score": 131.34,
    "rank": 2
  },
  {
    "_id": "61f0a163c6a48a907bd11a77",
    "contract_id": "asac.near",
    "token_series_id": "39",
    "creator_id": "asac.near",
    "in_circulation": 1,
    "metadata": {
      "name": "Antisocial Ape Club #40",
      "symbol": "ASAC",
      "description": "A collection of 3333 unique, randomly generated pixel art ape NFTs stored on the NEAR blockchain.",
      "seller_fee_basis_points": 500,
      "image": "image.png",
      "external_url": "https://antisocialape.club/",
      "attributes": [
        {
          "trait_type": "Antisocial Ape Club",
          "value": "Genesis Apes",
          "rarity_score": "1.00"
        },
        {
          "trait_type": "Skin",
          "value": "Gingerbread",
          "rarity_score": "100.00"
        },
        {
          "trait_type": "Mouth",
          "value": "Blunt",
          "rarity_score": "3.45"
        },
        {
          "trait_type": "Eyes",
          "value": "Red Vr Headset",
          "rarity_score": "14.29"
        },
        {
          "trait_type": "Head",
          "value": "None",
          "rarity_score": "5.00"
        },
        {
          "trait_type": "Neck",
          "value": "None",
          "rarity_score": "1.37"
        },
        {
          "trait_type": "Earrings",
          "value": "Silver Stud",
          "rarity_score": "3.33"
        }
      ],
      "properties": {
        "files": [
          {
            "uri": "image.png",
            "type": "image/png"
          }
        ],
        "category": "image",
        "creators": [
          {
            "address": "asac.near",
            "share": 100
          }
        ]
      },
      "title": "Antisocial Ape Club #40",
      "media": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/39.png",
      "media_hash": null,
      "issued_at": "1643133670278506382",
      "expires_at": null,
      "starts_at": null,
      "updated_at": null,
      "extra": null,
      "reference": "https://ipfs.io/ipfs/bafybeicj5zfhe3ytmfleeiindnqlj7ydkpoyitxm7idxdw2kucchojf7v4/39.json",
      "reference_hash": null,
      "creator_id": "asac.near",
      "collection": null,
      "score": 132.14806994411788
    },
    "price": null,
    "royalty": {
      "asac.near": "500"
    },
    "isMediaCdn": true,
    "collection": null,
    "lowest_price": null,
    "updated_at": 1651360595494,
    "has_price": null,
    "total_rarity_score": 128.44,
    "rank": 3
  },
]

const filters = 
{
  TRAIT_TYPE: [
    "Earrings"
  ]/*,
  SOME_OTHER_FILTER: [
    ...
  ]
  */
}

const filtered = data.filter((d) => {
 let traitTypePasses = false;
 // let some_other_filterPasses = false;
  
  for(let filter in filters) {
    if(filter === "TRAIT_TYPE") {
      let traits = d.metadata.attributes
      .filter((a) => filters[filter].includes(a.trait_type));
      
      traitTypePasses = traits.length > 0;
    }
    
    /*
    
    if(filter === "SOME_OTHER_FILTER") {
      let traits = d.metadata.attributes
      .filter((a) => filters[filter].includes(a.trait_type));
      
      some_other_filterPasses = traits.length > 0;
    }
    
    */
  }
  
  return [traitTypePasses/*, some_other_filterPasses */].every((p) => p);
});

console.log(filtered.map((x) => x._id));

You define your filters in the filter-object like shown.

Then we have this piece:

const filtered = data.filter((d) => {
 let traitTypePasses = false;
 // let some_other_filterPasses = false;
  
  for(let filter in filters) {
    if(filter === "TRAIT_TYPE") {
      let traits = d.metadata.attributes
      .filter((a) => filters[filter].includes(a.trait_type));
      
      traitTypePasses = traits.length > 0;
    }
    
    /*
    
    if(filter === "SOME_OTHER_FILTER") {
      let traits = d.metadata.attributes
      .filter((a) => filters[filter].includes(a.trait_type));
      
      some_other_filterPasses = traits.length > 0;
    }
    
    */
  }
  
  return [traitTypePasses/*, some_other_filterPasses */].every((p) => p);
});

We can define a "local pass" value for each filter defined in the filter array. All filters must pass for the object in data to pass the main filter. So if you have a second if-block there, filtering by _id for example, the code will check the each object if they have the given _id AND the given attributes in the other filter - if it doesn't the object won't pass to the final, filtered array.

  • Related