How to merge objects with Lodash, but replace arrays values? - lodash

I'm trying to replace arrays of an old object with values from a new object which has arrays... I guess it will make sense when you see an example and desire result:
https://jsfiddle.net/redlive/9coq7dmu/
const oldValues = {
a: 1,
b: [2, 21, 22, 23],
c: {
d: 3,
e: 4,
f: [5, 6, 7]
}
};
const updatedValues = {
b: [],
c: {
f: [8]
}
}
const result = _.merge( oldValues, updatedValues );
console.log(result);
/* Desire result:
{
a: 1,
b: [],
c: {
d: 3,
e: 4,
f: [8]
}
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

Use _.mergeWith(), and if the 2nd value is an array, return it. If not return undefined, and let merge handle it:
const oldValues = {"a":1,"b":[2,21,22,23],"c":{"d":3,"e":4,"f":[5,6,7]}};
const updatedValues = {"b":[],"c":{"f":[8]}};
const result = _.mergeWith(oldValues, updatedValues, (a, b) =>
_.isArray(b) ? b : undefined
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

Related

How to extract second level keys out of two level map using lodash

I have a data structure like this
{
'a' : { 'aa' : { b: 1, c: 2}},
'b' : { 'bb' : { c: 3, d: 4}},
'c' : { 'cc' : { c: 3, d: 4}}
}
I'd like to map it using lodash into a flat structure like this:
{
'aa' : { b: 1, c: 2}},
'bb' : { c: 3, d: 4}},
'cc' : { c: 3, d: 4}},
}
I can do it using a side effect based approach with the code like this:
const flattened = {};
_(state.values)
.map(e => _.forEach(e, (e, k) => flattened[k] = e))
.value();
It does the job, but I am looking for a nicer pure functional way to do this.
Get the values of the original object, and merge them into a new object:
const obj = {
'a' : { 'aa' : { b: 1, c: 2}},
'b' : { 'bb' : { c: 3, d: 4}},
'c' : { 'cc' : { c: 3, d: 4}}
}
const result = _.merge({}, ..._.values(obj))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

How can I make a typed index in Zig

I have an algorithm that has two arrays with their respective indices. Only, it would be very easy to mix both indices and access one of the arrays with the wrong index. For example:
var array1 = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var index1 = 7; // the 8th element in array1, fine because array1 has a length of 10
var array2 = [_]u8{ 1, 2, 3, 4, 5 };
var index2 = 2; // the 3rd element in array2, fine because array2 has a length of 5
array2[index1] // woops, I used the wrong index with the wrong array
Is there a way to make a custom index type to associate an array with a specific type of index such that indexing an array with the wrong type of index will result in a compile error?
Such as:
var array1 = [_:Index1]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // with index type 'Index1'
var index1 : Index1 = 7; // index of type 'Index1'
var array2 = [_:Index2]u8{ 1, 2, 3, 4, 5 }; // with index type 'Index2'
var index2 : Index2 = 2; // index of type 'Index2'
array2[index1] // ERROR: array2 expects Index2 type index but Index1 type is used
const std = #import("std");
fn PickyArray(comptime T: type, n: usize, extra: anytype) type {
_ = extra;
return struct {
const Self = #This();
pub const Index = struct {
idx: usize,
};
unsafe_items: [n]T,
pub fn init(xs: [n]T) Self {
return .{.unsafe_items = xs};
}
pub fn get(self: Self, idx: Index) T {
return self.unsafe_items[idx.idx];
}
pub fn set(self: *Self, idx: Index, v: T) void {
self.unsafe_items[idx.idx] = v;
}
pub fn getPtr(self: Self, idx: Index) *T {
return &self.unsafe_items[idx.idx];
}
pub fn getSlice(self: Self, lo: Index, hi: Index) []T {
return self.unsafe_items[lo.idx..hi.idx];
}
};
}
const Array1 = PickyArray(u8, 10, "Index1");
const Index1 = Array1.Index;
const Array2 = PickyArray(u8, 5, "Index2");
const Index2 = Array2.Index;
pub fn main() void {
var array1 = Array1.init([_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
var index1 : Index1 = .{.idx=7}; // index of type 'Index1'
var array2 = Array2.init([_]u8{ 1, 2, 3, 4, 5 }); // with index type 'Index2'
var index2 : Index2 = .{.idx=2}; // index of type 'Index2'
_ = array2.get(index1); // ERROR: array2 expects Index2 type index but Index1 type is used
_ = array1;
_ = index1;
_ = array2;
_ = index2;
}
For extra credit, the type returned by getSlice should not be a normal slice and should refuse to accept integer indices.
Please do not do this.

Reducing to list of object from object key and value

Given a previous Ramda groupBy to
{
'2018-Q4': 2,
'2019-Q1': 5
}
How can I map this to
[
{'quarter': '2018-Q4', 'value': 2},
{'quarter': '2019-Q1', 'value': 5},
]
Convert to pairs and then zipObj with the field names:
const { pipe, toPairs, map, zipObj } = R
const fn = pipe(
toPairs,
map(zipObj(['quarter', 'value']))
)
const data = {
'2018-Q4': 2,
'2019-Q1': 5
}
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

Forward and current iterators

Is there was another way of writing this?
fn main() {
let mut a = [1, 2, 3, 4, 5];
let mut iter1 = a.iter();
let mut iter2 = a.iter().skip(1).peekable();
while iter2.peek().is_some() {
println!("iter1: {:?}, iter2: {:?}", iter1.next(), iter2.next());
}
}
I am not certain of what is the exact question but the code itself could be rewritten using the windows iterator:
fn main() {
let a = [1, 2, 3, 4, 5];
for w in a.windows(2) {
println!("elem1: {:?}, elem2: {:?}", w[0], w[1]);
}
}

Union of 2 objects with Lodash?

I have 2 objects:
var obj1 = { a:1, b:2, c:3 };
var obj2 = { a:4, c:5, d:6 };
How could I get the union of these 2 objects with lodash? I expect the result to be:
{ a:4, c:5 }
Here is a one-line and readable snippet:
_.pick(obj2, _.intersection(_.keys(obj1), _.keys(obj2)))
// {a: 4, c: 5}
jsfiddle: http://jsfiddle.net/ze8g0p22/