build array of only one property when condition is met - javascript

I am looking to filter an array of only one property from the filtered items.
I currently have:
let tools = permissions.filter(perm => {
if (perm.state === state) return perm.tool;
});
and that builds an array of perm objects. I am looking to have tools only filled with perm.tool. Is this possible?
example:
permissions =
[
{
state: 'NJ',
tool: 'email'
},
{
state: 'MA',
tool: 'print'
},
{
state: 'NJ',
tool: 'submit claim'
},
]
When state = 'NJ' , I am looking to get:
tools = ['email', 'submit claim']

What you want is a reduce
let tools = permissions.reduce((results, perm) => {
if (perm.state === state) {
results.push(perm.tool);
}
return results;
}, []);

You are probably looking for map after the filter:
let tools = permissions
.filter(perm => perm.state === state)
.map( el => el.tool );

let tools = (state) => {
return (permissions.reduce((acc, rec) => {
if (rec.state === state) {
return [...acc, rec.tool]
}
return [...acc]
}, [])
)
}

Here's a solution:
const permissions = [
{
state: 'NJ',
tool: 'email'
},
{
state: 'MA',
tool: 'print'
},
{
state: 'NJ',
tool: 'submit claim'
}
];
function getTools(state) {
const tools = [];
permissions.forEach(perm => {
if(perm.state == state) {
tools.push(perm.tool)
}
});
return tools;
}
console.log(getTools('NJ'));

Related

ag-grid-react: getSortModel is not a function

I'm trying to get sort model from ag-grid-react component using getSortModel() but I'm getting getSortModel is not a function
my code
onSortChanged={useCallback(e => console.log(e.api.getSortModel(), 'im from sort'))}
"#ag-grid-community/react": "27.3.0",
"#ag-grid-enterprise/all-modules": "27.3.0",
After spend some time found params.api.getSortModel() is deprecated after version 24.0.0.
Using Column state for get Sort model and set Sort model in the following way
getSortModel:
const onSortChanged = useCallback(() => {
const value = gridParams.columnApi.getColumnState().find(s => s.sort != null)
if (value) {
setSortModel([ value ])
} else {
setSortModel([])
}
}, [ gridParams, setSortModel ])
setSortModel:
useEffect(() => {
if (sortModel.length > 0) {
const curretSortModel = gridParams.columnApi.getColumnState()
const mergeSortModel = curretSortModel.map(o1 => sortModel.find(o2 => o2.colId === o1.colId) || o1)
gridParams.columnApi.setColumnState(mergeSortModel)
}
}, [gridParams, sortModel]
As per this plunkr, you can retrieve and apply sort with the following example: https://plnkr.co/edit/?open=index.jsx&preview
const sortByAthleteDesc = useCallback(() => {
gridRef.current.columnApi.applyColumnState({
state: [{ colId: 'athlete', sort: 'desc' }],
defaultState: { sort: null },
});
}, []);
const saveSort = useCallback(() => {
var colState = gridRef.current.columnApi.getColumnState();
var sortState = colState
.filter(function (s) {
return s.sort != null;
})
.map(function (s) {
return { colId: s.colId, sort: s.sort, sortIndex: s.sortIndex };
});
savedSort = sortState;
console.log('saved sort', sortState);
}, []);

deep filtering on array of objects

I have data like this one below
let data = [
{
name: 'basic',
to: 'aaa',
subMenus: [
{
name: 'general conc',
to: 'geneal',
},
{
name: 'example view',
to: 'example',
},
{
name: 'fancy',
to: 'bbb',
innerSubMenus: [
{
name: 'adding',
to: 'add',
},
{
name: 'getting',
to: 'get',
},
]
}
]
}
]
I need to filter data based on name (in main, subMenus, and innerSubMenus)
Here is the piece of code
function deepFilter(inputText){
data.filter(items => items.name.toLowerCase().includes(inputText.toLowerCase()))
}
As you can see, the function filters the first prop (name --> basic in this case when inputText = 'basic', doesn't work when inputText = 'general conc') but I want to be able to filter names in subMenus and innerSubMenus as well. Please, guide me on how to do it. Thanks
expected outputs:
deepFilter('basic') -> true // only this part is covered by my implementation
deepFilter('general conc') -> true
deepFilter('adding') -> true
deepFilter('ffff') -> false //since there is not name with value of 'ffff' in data
I think this should work well.
function deepFilter(inputText, datas) {
return datas.filter(data => {
function checkInsideObj(object, inputText) {
for (let value of Object.values(object)) {
if (object.name && object.name.toLowerCase() === inputText.toLowerCase()) {
return true;
}
if (Array.isArray(value)) {
return value.some(item => {
return checkInsideObj(item, inputText)
}
)
}
}
return false;
}
return checkInsideObj(data, inputText)
}
)
}
deepFilter("input", data)

Get bad values inside a loop

I've got a method for generate url
But I have a little problem when I'm adding the condition if/else, he returns me only the first value and not all
This is my code :
public generateUrl(components: any, versions: any) {
const keys: any[] = Object.keys(components); //['toto','titi','tata','tutu']
for (const component of keys) {
const versions = components[component].artifacts.map((arti) => {
return {
component: arti.name,
type: arti.type,
version: versions[arti.name],
};
});
console.log(versions); // Display only the first one and not all
//[ { component: 'toto',
// type: 'npm',
// version: '1' } ]
for (const i in versions) {
const v = versions[i];
// here i'm adding the confition
if (v.type === "jar") {
const urlTest =
v.component +
"/" +
v.version +
".jar"
return urlTest;
} else if (v.type === "npm") {
const urlTest =
v.component +
"/" +
v.version +
".npm"
return urlTest;
}
} else if (v.type === "rpm") {
const urlTest =
v.component +
"/" +
v.version +
".rpm"
return urlTest;
}
}
}
}
}
I need to retrieve all values and not only the first one.
THanks for your help
Use Array.prototype.reduce to accumulate your values which match up to your type, instead of returning after match.
Also the for-in loop is to enumerate over enumerable object properties of a object, if I am not mistaken then versions is an array.
Working example below -
const data = [
{
component: 'toto',
type: 'npm',
version: '1'
},
{
component: 'tata',
type: 'jar',
version: '2'
},
{
component: 'titi',
type: 'rpm',
version: '3'
}
];
const types = ['npm', 'jar', 'rpm'];
const testUrls = data.reduce((acc, { component, type, version }) => {
if (types.includes(type)) {
acc.push(`${component}/${version}.${type}`);
}
return acc;
}, []);
console.log(testUrls);
like #Bergi said
That's because you return from the first iteration of the loop.
else you can try something like that, by using reduce:
Working example:
type Component = {
artifacts: any[];
};
type Version = {
[key: string]: string;
}
class Test {
public static GenerateUrl(components: Component[], versions: Version) {
return components.reduce((acc: any, { artifacts }) => {
return artifacts.reduce((acc, { type, name }) => {
acc.push(`${name}#${versions[name]}.${type}`);
return acc.flat();
}, acc);
}, []);
}
};
const versions: any = {
"titi": "1.0.0",
"toto": "1.8.1",
"tata": "1.2.5"
}
const components = [
{
artifacts: [
{
type: "jar",
name: "titi"
},
{
type: "npm",
name: "titi"
},
{
type: "rpm",
name: "toto"
},
{
type: "rpm",
name: "tata"
}
]
}
]
console.log(Test.GenerateUrl(components, versions)); // ["titi#1.0.0.jar","titi#1.0.0.npm","toto#1.8.1.rpm","tata#1.2.5.rpm"]

remove full object from Redux initial state when there is no values in the corresponding items

In my reducer, I have the initial state which looks like this:
const initialState = {
isLoading: false,
events: [
{
year: 2021,
place: [
{
id: 1,
name: "BD"
},
{
id: 2,
name: "BD Test"
}
]
},
{ year: 2020, place: [{ id: 3, name: "AMS" }, { id: 4, name: "AMS TEST" }] }
]
};
I have been trying to implement the functionality of deletion operation. So, when the button will be clicked the "deleteItems" action will be dispatched that will remove the corresponding items from the place. This functionality works fine. But,I am trying to remove the whole items from the events array if there is no values in place.
This is what I have tried already but it just removes the individual place. But, I need to write the logic here of removing the whole items when place becomes empty.
case "deleteItems":
return {
...state,
events: state.events.map(event => {
const place = event.place.find(x => x.id === action.id);
if (place) {
return {
...event,
place: event.place.filter(x => x.id !== action.id)
};
}
return event;
})
};
So, after modifications, the state would look like this:(when there is no values in place for year 2021)
const initialState = {
isLoading: false,
events: [
{ year: 2020, place: [{ id: 3, name: "AMS" }, { id: 4, name: "AMS TEST" }] }
]
};
Does anybody know how to accomplish this. Any helps would be highly appreciated.Thanks in Advance.
Demo can be seen from here
I removed the places first.
Then I filtered events based on whether the place array is empty or not.
After that, I returned the state.
case "deleteItems":
const eventsPostDeletingPlaces = state.events.map(event => {
const place = event.place.find(x => x.id === action.id);
if (place) {
return {
...event,
place: event.place.filter(x => x.id !== action.id)
};
}
return event;
});
const eventsWithPlaces = eventsPostDeletingPlaces.filter((each) => each.place.length);
return {
...state,
events: eventsWithPlaces
}
Check the edited sandbox here
Basically the same logic as in the first answer, but with reduce instead of a map and an extra filter. Just an option.
case "deleteItems":
return {
...state,
events: state.events.reduce((events, event) => {
const place = event.place.find(x => x.id === action.id);
if (place) {
event.place = event.place.filter(x => x.id !== action.id);
}
if (event.place.length > 0) {
events.push(event);
}
return events;
}, [])
};
codesandbox

How to create an observable stream of custom objects using RxJS operators

I currently have input which looks as follows
const config = {
'mainA': { sub1: { name: 'test1'}, sub2: { name: 'test2'}},
'mainB': { sub1: { name: 'test3'}, sub2: { name: 'test4'}}
};
I'm trying to write a function (createCustomObservable) which would create an observable using standard RsJS operators as follows
var observable = createCustomObservable(config);
observable.subscribe((x) => console.log(x));
The console output should read as follows
{'mainA': 'test1'} -> {'mainA': 'test2'} -> {'mainB': 'test3'} -> {'mainB': 'test4'}
A series of objects with a single propery
Does anyone have any idea how to realise this using RxJS operators? Any help would be appreciated.
The main problem for what you trying to solve is traverse the object to get all the objects that contains the "name" field, and get their value.
There's no Rx operator to automatically do that, so to achieve this task you can simply use Rx.Observable.create - https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/create.md
const config = {
'mainA': {
sub1: {
name: 'test1'
},
sub2: {
name: 'test2'
}
},
'mainB': {
sub1: {
name: 'test3'
},
sub2: {
name: 'test4'
}
}
};
function traverse(o, func) {
for (var i in o) {
func.apply(this, [i, o[i]]);
if (o[i] !== null && typeof(o[i]) == "object") {
//going on step down in the object tree!!
traverse(o[i], func);
}
}
}
var source = Rx.Observable.create(function(observer) {
traverse(config, function(key, value) {
if (key == "name")
observer.onNext(value);
});
observer.onCompleted();
return function() {
console.log('disposed');
};
});
source.subscribe(function(next) {
console.log(next);
})
Sample: https://jsbin.com/yolufovubi/edit?js,console
we can create a new stream by Observable constructor, You have to manually call next(), error() and complete() functions.
function createCustomObservable(config) {
return new Observable(
observer => {
try {
observer.next(config)
} catch(err) {
observer.error(err);
} finally {
observer.complete();
}
})
}
and use it this way
var observable = createCustomObservable(config);
observable.subscribe((x) => console.log(x));

Categories

Resources