search a string from an array whose keys and values are dynamic - javascript

I have the following array :
var Array = [{id:100,name:'N1',state:'delhi',country:'india',status:'active'},
{id:101,name:'N2',state:'kenya',country:'africa',status:'suspended'}
{id:102,name:'N3',state:'kerala',country:'india',status:'inactive'}
{id:103,name:'N4',state:'victoria',country:'australia',status:'active'}]
and I have a search field , where I need to filter the array with that searched value and return the matched object. The problem here for me is I donot know what key and value pairs may come in the above array , Key value pairs are generated dynamically ,also how can I search the array using Regex . It should match with each char I type and return the matching object in an array ? the result should look something like this :
search key : ind
[{id:100,name:'N1',state:'delhi',country:'india',status:'active'},
{id:102,name:'N3',state:'kerala',country:'india',status:'inactive'}]
search key : N2
[{id:101,name:'N2',state:'kenya',country:'africa',status:'suspended'}]
Any suggestions would be appreciated. Thanks

You could filter the array and check the value by a direct check, if you need to seach for parts of strings or for case independent values.
function search(value) {
return array.filter(o => Object.values(o).some(v => v === value));
}
var array = [{ id: 100, name: 'N1', state: 'delhi', country: 'india', status: 'active' }, { id: 101, name: 'N2', state: 'kenya', country: 'africa', status: 'suspended' }, { id: 102, name: 'N3', state: 'kerala', country: 'india', status: 'inactive' }, { id: 103, name: 'N4', state: 'victoria', country: 'australia', status: 'active' }];
console.log(search('india'));
console.log(search('N2'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

Convert array of objects to another array of objects

I need to convert array of objects to just objects to use it in table datasource:
{v_report_full: Array(25)}
v_report_full: Array(25)
0:
first_name: "Blake"
last_name: "Thorphan"
middle_name: "Agder"
monh: "2021-02-01 00:00:00"
n_vh: "Delay 00:04:52"
n_vh_s_obeda: "ok"
n_vyh: "ok"
n_vyh_s_obeda: "ok"
name: "oitib"
rtime: null
vh_s_obeda_ts: null
vhod_ts: "2021-02-01 08:59:52"
vyh_s_obeda_ts: null
vyhod_ts: null
__typename: "Ereport"
__proto__: Object
1:.. the same next index
2:.. the same next index
Table datasource requires next order:
const dataSource = [
{
key: '1',
name: 'Mike',
age: 32,
address: '10 Downing Street',
},
{
key: '2',
name: 'John',
age: 42,
address: '10 Downing Street',
},
];
I've tried to use Object.keys, but have not enough expirience to do that. If here is a simple solution, if not I have to write a loop for each row with function to concat, etc?
Upd. These one was I worked with:
let dataSource = (data) ? data.v_report_full.map((value, index, array) => {
return {
id: value.id,
key: value.id,
first_name:(value, 'first_name'),
.....
}
After hatfield advise, I checked once more and it's working! A liitle changes and above code then working now D: What a noob I am.

Filter object by property that starts with any of array elements

I have an object of contacts where I need to filter by the country code, for which I need to check if the ID of the contact (phone number) starts with any of the selected country codes array.
var countries = ['1', '91', '55', '972'];
var allContacts = [
{
id: '9123242135321',
name: 'Harun'
},
{
id: '905366365289',
name: 'Koray'
},
{
id: '135366365277',
name: 'Hayo'
},
{
id: '963923824212',
name: 'Bahaa'
},
{
id: '513324515689',
name: 'Hassan'
}];
I am looking for an efficient one-line solution without looping, so what I have tried before is:
allContacts.filter(c => c.id.some(l => countries.includes(l)));
But that worked if the id parameter is an array, and it searches the whole number instead of the beginning, what is the efficient way to filter the contacts which their id key startsWith any of the countries array values?
You need to iterate the countries and check with startsWith.
const
countries = ['1', '91', '55', '972'],
allContacts = [{ id: '9123242135321', name: 'Harun' }, { id: '905366365289', name: 'Koray' }, { id: '135366365277', name: 'Hayo' }, { id: '963923824212', name: 'Bahaa' }, { id: '513324515689', name: 'Hassan' }];
console.log(allContacts.filter(({ id }) => countries.some(c => id.startsWith(c))));

Filter an array of objects upon a value inside an array of objects inside in javascript

I am fetching an array of objects as following :
const data =
[ { id: 0, company: 'nike', items: [{ id: 0, name: 'caret', price: 100}] }
, { id: 1, company: 'adidas', items: [{ id: 1, name: 'mobile phone', price: 300}] }
]
I want to filter that array of objects by checking the value of the property "name" inside the items array if it is "Caret" or not. If yes, I want to return the same array of objects with all its content but filtered. Which means, it will filter out the object whose item's name is not caret. How can I achieve this in javascript?!
I suppose you are looking for that ?
const data =
[{ id: 0, company: 'nike', items: [{ id: 0, name: 'caret', price: 100}]}
,{ id: 1, company: 'adidas', items: [{ id: 1, name: 'mobile phone', price: 300}]}
]
const filterName = (arr, name)=>arr.filter(el=>el.items.some(x=>x.name==name))
onlyCaret = filterName(data,'caret')
console.log( onlyCaret[0].company ) // nike
console.log( onlyCaret ) // row 0 with { ... company: 'nike' ..}
.as-console-wrapper { max-height: 100% !important; top: 0; }
You need to use Array.filter and then loop through your items for a match
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const data = [
{
id:0,
company: "nike"
items:[
name: "caret",
price:100
]
},
{
id:1,
company: "adidas"
items:[
name: "mobile phone",
price: 300
]
},
]
const filteredCompanies = data.filter((company)=>{
company.items.forEach((item)=>{
if(item.name === "nike") return true
})
})

Filter array of objects based on multiple values from another array of objects

I have an array of objects,
c = [
{
name: 'abc',
category: 'cat1',
profitc: 'profit1',
costc: 'cost1'
},
{
name: 'xyz',
category: '',
profitc: 'profit1',
costc: ''
},
{
name: 'pqr',
category: 'cat1',
profitc: 'profit1',
costc: ''
}
]
Now I want to filter array based on another array of objects, the second array of objects is,
arr = [
{
type:'profitc'
value: 'profit1',
},
{
type:'category'
value: 'cat1',
}
]
Now the arr is shown in dropdown with multiple select option and the value of key value in the object is shown to the user i.e profit1, cat1, etc. So if a user selects profit1 and cat1, then I need to filter the array c such that, the output looks like this.
c = [
{
name: 'abc',
category: 'cat1',
profitc: 'profit1',
costc: 'cost1'
},
{
name: 'pqr',
category: 'cat1',
profitc: 'profit1',
costc: ''
}
]
I tried doing this.
let result = c.filter(e => {
let istruecat = true
//arr is chosen value from user.
arr.forEach(element => {
istruecat = e[element.type] == element.value;
})
return istruecat;
})
But when I do this I get all the objects from the c array. What am I doing wrong here? Is there a an way to do this using lodash.
-You compute istruecat based only on the last entry in arr. You should use reduce instead to accumulate value:
let result = c.filter(e => arr.reduce((acc, element) => acc && e[element.type] === element.value, true))
You could filter the array by checking all given key/values pairs with the data's objects.
var data = [{ name: 'abc', category: 'cat1', profitc: 'profit1', costc: 'cost1' }, { name: 'xyz', category: '', profitc: 'profit1', costc: '' }, { name: 'pqr', category: 'cat1', profitc: 'profit1', costc: '' }],
filters = [{ type: 'profitc', value: 'profit1', }, { type: 'category', value: 'cat1' }],
result = data.filter(o => filters.every(({ type, value }) => o[type] === value));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's an implementation of reducing the list c based in the given values by the filter array arr. Note that the output is a new list based on the initial content in c.
result = arr.reduce((acc, curr) => {
acc = acc.filter(item => {
return item[curr.type] === curr.value;
});
return acc;
}, c);
Or a recursive and imo readable solution:
function myFilter(c, [first, ...rest]) {
if (first) {
const {type, value} = first;
// Recursively call myFilter with one filter removed
return myFilter(c, rest)
.filter(x => x[type] === value);
} else {
// Nothing left to filter
return c;
}
}
myFilter(c, arr);

How to groupBy an object key inside nested array of objects?

I have a nested array of objects and I want to groupBy id and form a new array. Here's my array:
mainArray = [
{ name: 'a',age: 10, company: [ { desc: 'test1' , id: 6 }, { desc: 'testa' , id: 10 }] },
{ name: 'b',age: 20, company: [ { desc: 'test2' , id: 30 }] },
{ name: 'c',age: 40, company: [ { desc: 'test3' , id: 10 }, { desc: 'testc' , id: 30 }] }
]
I can flatten the entire array but it doesn't seem like the right way to do it.
My new array should look like something like this:
result = [
comapny_6: [
{
name: 'a',
age: 10,
desc: 'test1'
},
],
comapny_10: [
{
name: 'a',
age: 10,
desc: 'testa'
},
{
name: 'c',
age: 40,
desc: 'test3'
}
],
company_30 :[
{
name: 'b',
age: 20,
desc: 'test2'
},
{
name: 'c',
age: 40,
desc: 'testc'
}
]
]
I am open to suggestions on how the final data structure should look like. The bottom line is I want groupBy id so that I have information about each company separated out.
You can use reduce to loop thru the array and construct the desired object output. Use forEach to loop thru company
var mainArray = [{"name":"a","age":10,"company":[{"desc":"test1","id":6},{"desc":"testa","id":10}]},{"name":"b","age":20,"company":[{"desc":"test2","id":30}]},{"name":"c","age":40,"company":[{"desc":"test3","id":10},{"desc":"testc","id":30}]}];
var result = mainArray.reduce((c, {name,age,company}) => {
company.forEach(({id,desc}) => (c["company_" + id] = c["company_" + id] || []).push({name,age,desc}));
return c;
}, {});
console.log(result);
You can first create a 1D array using flatMap() and then use reduce() to group
const mainArray = [
{ name: 'a',age: 10, company: [ { desc: 'test1' , id: 6 }, { desc: 'testa' , id: 10 }] },
{ name: 'b',age: 20, company: [ { desc: 'test2' , id: 30 }] },
{ name: 'c',age: 40, company: [ { desc: 'test3' , id: 10 }, { desc: 'testc' , id: 30 }] }
]
const flat = mainArray.flatMap(({company,...rest}) => company.map(a => ({...rest,...a})));
const res = flat.reduce((ac,{id,...rest}) => ((ac[`company_${id}`] || (ac[`company_${id}`] = [])).push(rest),ac),{})
console.log(res)
Explanation
reduce() is method with returns a single value after iterating through all the array. The accumulator i.e ac in above case is set to empty object {}(which is the second argument passed to function)
In each iteration we return the updated accumulator which becomes ac for next iteration. So what we return from function is following expression
((ac[`company_${id}`] || (ac[`company_${id}`] = [])).push(rest),ac)
ac[company_${id}] is using Bracket Notation which takes an expression company_${id}. It is same as
ac["company_" + id]
The above line checks if ac[company_${id}] exists in the ac then push() rest to the it.
If ac[company_${id}] is not created yet they set it to empty array [] then push() the rest to it.
The last part uses comma operator
((ac[`company_${id}`] || (ac[`company_${id}`] = [])).push(rest),ac)
The above whole expression will evaluate to the last value separated by comma , which is ac. So in each iteration we are pushing rest to the respective array and returning ac it the end. The code is equivalent to
const res = flat.reduce((ac,{id,...rest}) => {
//check if company id doesnot exist as key in ac then set it empty array
if(!ac[`company_${id}`]) ac[`company_${id}`] = [];
//push rest(which will be an object with all the keys expect id)
ac[`company_${id}`].push(rest)
//at last return ac
return ac;
})
You can achieve this with Array.reduce and inside it with an Array.forEach over the array of companies like this:
let data = [ { name: 'a',age: 10, company: [ { desc: 'test1' , id: 6 }, { desc: 'testa' , id: 10 }] }, { name: 'b',age: 20, company: [ { desc: 'test2' , id: 30 }] }, { name: 'c',age: 40, company: [ { desc: 'test3' , id: 10 }, { desc: 'testc' , id: 30 }] } ]
let result = data.reduce((r,{ name, age, company }) => {
company.forEach(({ id, desc }) =>
r[`company_${id}`] = (r[`company_${id}`] || []).concat({ name, age, desc }))
return r
}, {})
console.log(result)

Categories

Resources