function merger(objValue, srcValue, key, object, source, stack) {
switch (key) {
case 'keya':
case 'keyb':
case 'keyc':
return null
}
}
mergeWith({}, oldObj, newObj, merger)
I would like to skip merging when key is equal to some value. But the output from above code will have the output as {keya: null} when newObj has keya.
Can I skip the merge so that the key is not in the output?
Simple answer: It is not possible with _.mergeWith.
You can see here https://github.com/lodash/lodash/issues/2966. You have to delete the null valued properties again with another process. Like,
_.omitBy(mergedObj, _.isNull);
This can totally be done like this:
function customMerge(destination, source, skip) {
return _.mergeWith(
destination,
source,
(objValue, srcValue, key) => {
if (srcValue === skip) {
_.unset(destination, key);
}
}
);
}
Here's an implementation of omitDeep that will omit any key/value that passes the predicate anywhere in the object structure.
function omitDeep(value, predicate = (val) => !val) {
return _.cloneDeepWith(value, makeOmittingCloneDeepCustomizer(predicate))
}
function makeOmittingCloneDeepCustomizer(predicate) {
return function omittingCloneDeepCustomizer(value, key, object, stack) {
if (_.isObject(value)) {
if (_.isArray(value)) {
return _(value).reject(predicate).map(item => _.cloneDeepWith(item, omittingCloneDeepCustomizer))
}
const clone = {}
for (const subKey of Object.keys(value)) {
if (!predicate(value[subKey])) {
clone[subKey] = _.cloneDeepWith(value[subKey], omittingCloneDeepCustomizer)
}
}
return clone
}
return undefined
}
}
Related
I am still coming up to speed with dart and wanted to know if there was an easier way to not execute a statement if the value is null. See example below:
I can always do the if statements below for setting field3 and field4, but felt like something like field5 should work. But when I try to do that, it complains that a null check operator is used on a null value.
Also I don't want to change the Map to have a dynamic value.
Is there a single one liner to do what I am trying to do, or do I just need to check for null before setting the value.
Map<String, Object> myMap = {};
print('running now');
try {
myMap['field1'] = DummyClass.getString('hello');
myMap['field2'] = DummyClass.getString('good');
//Is there a more concise way to do this than the 2 options below?
if (DummyClass.getOptionalString('goodbye') != null) {
myMap['field3'] = DummyClass.getOptionalString('goodbye')!;
}
String? temp = DummyClass.getOptionalString('go');
if (temp != null) {
myMap['field4'] = temp;
}
// This gives an error 'null check operator used on a null value'
// myMap['field5'] ??= DummyClass.getOptionalString('to')!;
} catch (e) {
print('error condition, $e');
}
print(myMap);
}
class DummyClass {
static String getString(String? strParam) {
String? retString = getOptionalString(strParam);
if (retString == null) {
throw ('nulls are not allowed');
}
return retString;
}
static String? getOptionalString(String? strParam) {
if (strParam == null || strParam.length < 3) {
return null;
}
return strParam;
}
}
There's no built-in way to do what you want, but you could write a function (or extension method) to do it. For example:
extension MapTrySet<K, V> on Map<K, V> {
void trySet(K key, V? value) {
if (value != null) {
this[key] = value;
}
}
}
and then you could do:
myMap.trySet('field3', DummyClass.getOptionalString('goodbye'));
myMap.trySet('field4', DummyClass.getOptionalString('go'));
Alternatively, if you really want to use normal Map syntax, you could create your own Map class that has a void operator []=(K key, V? value) override and does nothing when the value is null, but that probably would not be worth the effort.
The issue is that the ??= operator assigns to the left if it is null. Expanded, it would look something like this:
a ??= b;
// Equivalent to:
if (a == null) {
a = b;
}
Which is not something that you're trying to achieve. AFAIK, there is no such operator yet in Dart. However, you can try this:
final possiblyNullValue = '';
final myMap = <String, String>{};
myMap['key'] = possiblyNullValue ?? myMap['key'];
// Equivalent to:
if (possiblyNullValue != null) {
myMap['key'] = possiblyNullValue;
}
// or:
myMap['key'] = possiblyNullValue != null? possiblyNullValue : myMap['key'];
Which would work in your case as a one-liner.
You could create your map with all entries, even null, and then filter the null values out:
void main() {
try {
final myMap = <String, dynamic>{
'field1': DummyClass.getString('hello'),
'field2': DummyClass.getString('good'),
'field3': DummyClass.getOptionalString('goodbye'),
'field4': DummyClass.getOptionalString('go'),
}..removeWhere((k, v) => v == null);
print(myMap);
} catch (e) {
print('error condition, $e');
}
}
i use spring boot's RedisTemplate with scala, and i write this code:
redisTemplate1.executePipelined(new RedisCallback[String] {
override def doInRedis(connection: RedisConnection): String = {
MyCode......
null
}
}, redisTemplate1.getValueSerializer)
usually, it's can be wrote like this:
redisTemplate1.executePipelined((connection: RedisConnection) => {
MyCode......
null
}, redisTemplate1.getValueSerializer)
and this style is running well in java:
redisTemplate1.executePipelined((RedisConnection conn) -> {
MyCode......
return null;
}, redisTemplate1.getValueSerializer());
but when i compile in this style with scala, i get an error, so why this happend and how can i use single abstract method in this case?
overloaded method value executePipelined with alternatives:
(x$1: org.springframework.data.redis.core.RedisCallback[_],x$2: org.springframework.data.redis.serializer.RedisSerializer[_])java.util.List[Object] <and>
(x$1: org.springframework.data.redis.core.SessionCallback[_],x$2: org.springframework.data.redis.serializer.RedisSerializer[_])java.util.List[Object]
cannot be applied to (org.springframework.data.redis.connection.RedisConnection => Null, org.springframework.data.redis.serializer.RedisSerializer[?0(in method syncSegmentSrc)])
redisTemplate1.executePipelined((connection: RedisConnection) => {
the executePipelined function source code like this:
#Override
public List<Object> executePipelined(SessionCallback<?> session, #Nullable RedisSerializer<?> resultSerializer) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
try {
return execute((RedisCallback<List<Object>>) connection -> {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = executeSession(session);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
#Override
public List<Object> executePipelined(RedisCallback<?> action, #Nullable RedisSerializer<?> resultSerializer) {
return execute((RedisCallback<List<Object>>) connection -> {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = action.doInRedis(connection);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
}
In cases like this, it should help to specify the type explicitly:
redisTemplate1.executePipelined({ connection =>
YourCode…
}: RedisCallback[String], redisTemplate1.getValueSerializer)
Note the type ascription : RedisCallback[String].
I am trying to check the name of a key in a list and then change the name if it meets a certain criteria.
My code so far is:
String convert(double key) {
if(key == '1') {
return "One";
} else if(key == '2') {
return "Two";
}
//This the the list loop:
for (var entry in optoins.entries) {
entry.key = convert(entry.key); //This seems to be incorrect
if (entry.key == "One") {
//do somehting
}
}
The error I get is this one:
The argument type 'String' can't be assigned to the parameter type 'double'.
I know I can do if (entry.key == "1") but later in the code I need entry.key to be a string One and not 1, so I would like to change the name before starting the if else check.
The problem is your code entry.key is a double variable and not a string. I would suggest adding a new field to the entry class called stringKey and store this value there. That would be something like
String convert(String key) {
if(key == '1') {
return "One";
} else if(key == '2') {
return "Two";
}
//This the the list loop:
for (var entry in optoins.entries) {
entry.stringKey= convert(str(entry.key)); //This seems to be incorrect
if (entry.stringKey== "One") {
//do somehting
}
}
Consider a function in Dart file
void myFunction({int input = 1, Function(int, String) callback}) {
// ...
}
So, I wonder is it possible at all to specify a default value for the callback parameter, for instance it can be something like (_, _) => { }.
P.S. I know it has null as default value and ?? can help to avoid NPE, I'm just curious is it possible at all. Cheers.
You can do something like:
dynamic func(int i, String s) {
print(i.toString() + s);
}
void myFunction({int input = 1, Function(int, String) callback = func}) {
callback(input, " .");
}
void main() {
myFunction(input: 2);
}
The default value of an optional parameter must be constant.
This is what the documents said
This thing can be bypassed like this:
dynamic myCallback(int a,String b) {
}
void myFunction({int input = 1, Function(int, String) callback }) {
if (callback == null) callback = myCallback;
}
Edit:
Alternatively, you can use anonymos functaion with out myCallback funcation like this:
void myFunction({int input = 1, Function(int, String) callback }) {
if (callback == null) callback = (a,b){};
}
I'm creating an observable and I'm creating the subscription separately:
class CustomQuery {
string Name;
IObservable<int> Occurrences;
}
public IEnumerable<CustomQuery> GatherCustomQueryObservables()
{
yield return new CustomQuery() {
Name = "NameXXX",
Occurrences = Observable.Create<int>(
observer =>
{
int occurrences = this.webservice.GetOccurrences()
observer.OnNext(occurrences);
return System.Reactive.Disposables.Disposable.Empty;
}
);
}
By other hand, there's another method deals with these CustomQueries:
public void CommitCustomQueryObservables(IEnumerable<CustomQuery> queries)
{
foreach (CustomQuery query in queries)
{
query.Occurrences
.Select(o => o)
.SubscribeOn(System.Reactive.Concurrency.TaskPoolScheduler.Default)
.ObserveOn(System.Reactive.Concurrency.DispatcherScheduler.Current)
.Subscribe(
occurrences =>
{
string strOccurrences = occurrences > 0 ? occurrences.ToString() : "";
this.Label.Text = strOccurrences;
}
);
}
}
Nevertheless, I'm getting a System.InvalidOperationException exception:
The current thread has no Dispatcher associated with it.
The last line of the stacktrace is at
System.Reactive.Concurrency.DispatcherScheduler.get_Current().
I don't quite figure out how to handle it.
Any ideas?
For Windows Forms you need to use the ControlScheduler for synchronization, not the DispatcherScheduler.
Now you've added the System.Reactive.Windows.Forms package this can be achieved by simply using [observable].ObserveOn([control]); in your example this could be:
public void CommitCustomQueryObservables(IEnumerable<CustomQuery> queries)
{
foreach (CustomQuery query in queries)
{
query.Occurrences
.Select(o => o)
.SubscribeOn(System.Reactive.Concurrency.TaskPoolScheduler.Default)
.ObserveOn(this.Label)
.Subscribe(
occurrences =>
{
string strOccurrences = occurrences > 0 ? occurrences.ToString() : "";
this.Label.Text = strOccurrences;
}
);
}
}