-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: filter null values in map, returning keys #6
Comments
It doesn't seem like any of the functions is providing this kind of functionality, so I ended up with this custom
Or is there a simpler way to achieve this? :) |
Thanks for your suggestion. There is indeed a simpler way to achieve this already in R.apex. Please check below: Map<String, String> m = new Map<String, String>{
'Name' => 'Account',
'Description' => null,
'Website' => null
};
R.of(m)
.filter(R.isNotNull)
.keys()
.debug(); Or you can choose a more functional way like this: Map<String, String> m = new Map<String, String>{
'Name' => 'Account',
'Description' => null,
'Website' => null
};
Func f = (Func)R.pipe.run(
R.filter.apply(R.isNotNull),
R.keys
);
System.debug(f.run(m)); The thing here is that many functions in R.apex is polymorphic in that they accept multiple types of arguments. Take
When filtering on a map, the expecting predicate function in pred:: (value, key) => Boolean |
Aha, that's indeed a cleaner approach! Small question, is there a specific reason why the order of pred arguments is pred:: (value, key) and not pred:: (key, value) Or is this a standard in all other libraries like Lodash etc.? (I was kind of confused with the "logical inversion" of the args when writing my own predicate function) |
Well, that is actually kind of pain in the ass. This difference of usage is commonly seen between lodash and ramdajs. You can refer to this popular speech to get deeper understanding on this: Simply put, if we want to 'compose' functions in a more functional way, put the main data at last. Func filterNotNull = R.filter.apply(R.isNotNull); This composed function waits for the data to be filtered. If we do it in the other way, it would be like this: Func filterNotNull = R.otherFilter.apply(R.placeholder, R.isNotNull); Here the |
As to the predicate function, normally it takes one argument. So the first argument is supposed to be the main data. And in your example, |
@liumiaowilson Thank you for the explanation! Really appreciate it! Another thing I'm currently trying to do is; filter the fields that do not have a certain value (or a list of possible values). So I could pass a Map like this to the filter function: Map<String, List<String>> m = new Map<String, List<String>>{
'Name' => new List<String>{ 'TestAccount', 'TestAccount2' }
}; So if the field value for Is this still possible with the default filter functionality? |
It would be difficult to achieve it with the default filter functionality, I might say. Well, even if it is possible, I would still suggest that you create a custom function to implement this logic. It would be a shame if you go too far with functional composition in R.apex and lose the code readability. Do not do functional just for the sake of being functional programming. Just strike a balance between functional style and code readability. If I were you, I would create a custom function in this case. If it is kind of commonly used, I would put it in a class to reference it like this: public class CustomFuncs {
public static final Func filter = new CustomFilter();
} So I can reuse it wherever I want without creating another new instance. Object result = CustomFuncs.filter.run(m, data); |
Thanks! I came up with this: private class PropInFunc extends Func {
public PropInFunc() {
super(3);
}
public override Object exec(Object a, Object b, Object c) {
Object value = a;
Object key = b;
Map<String, Object> mMap;
if((Boolean)R.isMapLike.run(c)) {
mMap = (Map<String, Object>)c;
Object mValue = mMap.get((String)key);
if(mValue != null && (Boolean)R.isListLike.run(mValue)) {
return R.of(mValue).contains(value);
}
}
return false;
}
} and then call it like: R.filter.apply(new PropInFunc().apply(R.placeholder, R.placeholder, m)), with I could add it in an MR if you think it's reusable in R.apex? Anyway, thanks for the help! |
@glenncoppens Very good implementation. If you put the map as the first argument, you can call it like: R.filter.apply(new PropInFunc().apply(m)) That would be simpler, right? When you use R.of(mValue).contains(value).toBoolean()
So you can improve it to: if((Boolean)R.isMapLike.run(c)) {
mMap = (Map<String, Object>)R.toMap.run(c);
}
Sure you can add it in a PR, and do make sure to include tests and examples of how people are supposed to use this new functions. Good job. |
Hi,
Been playing around with the library, but I can't seem to get my head around the following (kind of new to fp):
Is it possible to only retrieve the keys where the value is
null
?The text was updated successfully, but these errors were encountered: