custom sum elements by key using lodash - lodash

I do have two objects containing keys like
var a = {bar:[1,2], foo:[7,9]}
var b = {bar:[2,2], foo:[3,1]}
I want to get the fallowing results:
var c = {bar:[3,4], foo:[10,10]}
I already have a for logic like:
for (let key in b) {
if (a[key]) {
a[key][0] += b[key][0];
a[key][1] += b[key][1];
}
else a[key] = b[key];
}
But I would like to make this logic in a lodash way. How can I Do it?

You can use create a function that takes n objects, and collects them to an array using rest parameters. Now you can spread the array into _.mergeWith() to combine the objects, and in the customizer function sum the items in the arrays using Array.map() or lodash's _.map() and _.add():
const { mergeWith, isArray, map, add } = _
const fn = (...rest) => _.mergeWith({}, ...rest, (o = [], s) =>
map(s, (n, i) => add(n, o[i]))
)
const a = {bar:[1,2], foo:[7,9]}
const b = {bar:[2,2], foo:[3,1]}
const c = {bar:[3,2], foo:[5,6]}
const d = {bar:[4,2], foo:[5,4]}
const result = fn(a, b, c, d)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You can also use lodash/fp to create a function that merges all values to a multidimensional array with _.mergeAllWith(), then transpose the arrays using _.zipAll(), and sums each array:
const { rest, flow, mergeAllWith, isArray, head, mapValues, zipAll, map, sum } = _
const fn = rest(flow(
mergeAllWith((o, s) => [...isArray(head(o)) ? o : [o], s]), // combine to a multidimensional array
mapValues(flow(
zipAll,
map(sum)
)),
))
const a = {bar:[1,2], foo:[7,9]}
const b = {bar:[2,2], foo:[3,1]}
const c = {bar:[3,2], foo:[5,6]}
const d = {bar:[4,2], foo:[5,4]}
const result = fn(a, b, c, d)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>

You can accomplish this using plain JavaScript with Object.entries, concat and reduce:
const a = { bar: [1,2], foo: [7,9] };
const b = { bar: [2,2], foo: [3,1] };
const entries = Object.entries(a).concat(Object.entries(b));
const result = entries.reduce((accum, [key, val]) => {
accum[key] = accum[key] ? accum[key].map((x, i) => x + val[i]) : val;
return accum;
}, { });
console.log(result);

Related

what is the difference between writing composables and exporting stuff separately?

We're developing an application on vue3-composition-api.
so we are developing scripts on this concept called composables. We use this composables in different places for reusing stuff instead of rewriting them, The problem is that some parts of the composables are created but not being used and it seems to have an impact on performance. Checkout these three approaches.
useFeatureA.js - FIRST APPROACH (using stateful composables)
export function useFeatureA() {
const x = ref(false)
const y = computed(() => {
// uses x.value
})
const z = computed(() => {
// uses x.value
})
const foo = () => {
// uses y.value and z.value
// sets on x.value
}
const bar = () => {
// uses z.value
// sets on x.value
}
return { y, foo, bar }
}
useFeatureA.js - SECOND APPROACH (exporting separately and recompute everytime)
export const getX = () => {
return ref(false);
}
export const getY = (x) => {
return computed(() => {
// uses x.value
});
}
export const foo = (xValue, yValue) => {
const z = // using xValue
// uses yValue and z
return // something to write on x
}
export const bar = (xValue) => {
const z = // using xValue
// uses and z
return // something to write on x
}
ComponentA
<script setup>
const { getX, getY, foo, bar } = useFeatureA();
const x = getX();
const y = getY(x);
x.value = foo(x.value, y.value);
x.value = bar(x.value);
</setup>
useFeatureA.js - THIRD APPROACH (move state to component)
export const getX = () => {
return ref(false);
}
export const getY = (x) => {
return computed(() => {
// uses x.value
});
}
export const getZ = (x) => {
return computed(() => {
// uses x.value
});
}
export const foo = (yValue, zValue) => {
// uses yValue and zValue
return // something to write on x
}
export const bar = (zValue) => {
// uses and z
return // something to write on x
}
ComponentA
<script setup>
const { getX, getY, foo, bar } = useFeatureA();
const x = getX();
const y = getY(x);
const z = getZ(x);
x.value = foo(y.value, z.value);
x.value = bar(z.value);
</setup>
we are wondering whether this solution can be efficient or not and what the differences between these two approaches are.
NOTE: We came up with the idea of separating those two functions in two different composables but the problem is that the project is too big and this approach makes way too many composables while foo and bar are very close to each other because of being related to a specific feature. so we guess this approach of separating them on different composables is out of question.
UPDATE: we have this idea that if we need stateful composable, the second approach is a bottleneck since if the components uses the composable, after the component is destroyed, the state remains in memory.
we guess in second approach tree-shaking is more efficient.

Multiple props in Ramda lens

Is there a way to apply transforms to multiple keys of an object in Ramda? I am aware this is achievable by R.evolve, but I am interested in knowing if this can be achieved by some modification of lenses.
E.g.:
const data = {
a: "100",
b: "non_numeric_string",
c: "0.5"
}
const numerize = x => +x
const mapping = {
a: numerize,
c: numerize
}
magicFunction(mapping, data)
output:
{
a: 100,
b: "non_numeric_string",
c: 0.5
}
The whole point of a lens is to focus on one part of a data structure. While it is not hard to write something using lensProp to achieve this, I'm don't think it's either very satisfying or a particularly appropriate use of lenses. Here's one Ramda solution:
const magicFunction = (mapping, data) =>
reduce
( (o, [k, fn]) => over (lensProp(k), fn, o)
, data
, toPairs (mapping)
)
const numerize = x => Number (x)
const mapping = {
a: numerize,
c: numerize
}
const data = {a: "100", b: "non_numeric_string", c: "0.5"}
console .log (
magicFunction (mapping, data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const { lensProp, over, reduce, toPairs } = R </script>
But note that a plain ES6 function does the job just as simply, without using lenses:
const magicFunction = (mapping, data) =>
Object.entries (mapping). reduce
( (o, [k, fn]) => ({...o, [k]: fn (o [k]) })
, data
)
Lenses simply don't gain you much here.

how to iterate through two arrays simultaneously with lodash

I have
A = [1,2,3,4,5,6,7]
B = [3,5,9]
I want to get an array C containing the last elements < than elements in B, like
C = [2,4,7], by using Lodash
I tried
C=_.map(A, a = (v) -> v == _.findLast(A, b = (v) -> v < _.forEach(B, c = (v) -> v==v)))
which does not work. Above I used coffeescript instead of javascript, but please reply with either, I want a solution using lodash, without explicit looping through B elements, thank you.
The forEach is redundant, and just returns the original collection:
const A = [1,2,3,4,5,6,7]
const B = [3,5,9]
// C = [2,4,7], by using Lodash
const result = _.map(B, n => _.findLast(A, m => m < n));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
I know you said you want a lodash soultion, but just in case you were curious here is a way to get your desired array using vanilla ES6:
const A = [1, 2, 3, 4, 5, 6, 7];
const B = [3, 5, 9];
const C = findEls(A, B);
function findEls(A, B) {
const copy = [...A].reverse(); //Copy since reverse is an in-place operation
return B.map(b => {
return copy.find(a => a < b);
});
}
console.log(C);

How do I apply a map function to a tensor ? (Tensorflow.js)

How can I apply a function to each elements of a tensor like
var new_tensor = old_tensor.map(map_function)
If you use the dataSync method of oldTensor you can get a TypedArray which you can map over.
var old_tensor_vals = old_tensor.dataSync()
var new_tensor_vals = old_tensor_vals.map(map_function)
If your map_function is specific enough, you can do it simply by using tensor math.
The function below is the implementation of:
old => Math.random()>chance?Math.random():old;
const old = tf.randomUniform([10], 0, 10);
const chance = 0.75;
const mapped = tf.tidy(() => {
const max = Math.round(100 * chance);
const min = max - 1;
const random = tf.randomUniform([old.shape[0]], 0, 100).floor();
const ones = random.clipByValue(min, max).sub(tf.scalar(min));
ones.print();
const zeros = ones.sub(tf.scalar(1)).neg();
zeros.print();
const newValues = tf.randomUniform([old.shape[0]]); //or whatever you want
//newValues.print();
return old.mul(ones).add(newValues.mul(zeros));
});
old.print();
mapped.print();
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#0.10.0">
</script>

Table, computed property and vuex data

I'm in need of help with computed properties .. it's hard to explain but I'll try ..
I have a table with filter and pagination that I created.
When I pass the data directly from a request the API works,
but when I have to work with data coming from vuex I'm having trouble ...
Because I do not know when the data will be filled in vuex
And then I use the computed property because the moment the vuex is filled it will capture the data ..
However as the function that fills the data is the same one that is executed when I click on the page I crash the process and the page stops working.
Below is the computed property:
list(){
if (this.url_get == '' && this.$store.state.table.list.length > 0){
this.total_data = this.$store.state.table.list.length
this.repos = this.$store.state.table.list
this.getPaginatedItems(1)
}
var filter = this.configs.filter.toString().toLowerCase()
var items = ''
if (filter == ''){
items = this.dados
}else{
items = this.repos
}
const list = this.$lodash.orderBy(items, this.configs.orderBy, this.configs.order)
this.reverse = 1;
if (this.$lodash.isEmpty(filter)) {
return list;
}
var result = this.$lodash.filter(list, repo => {
return repo[this.filter_term].toString().toLowerCase().indexOf(filter) >= 0
})
return result
},
And the function:
getPaginatedItems(data) {
var items = this.repos
var page = data
var per_page = 10
var offset = (page - 1) * per_page
var max_item = offset+per_page
var paginatedItems = this.$lodash.slice(items, offset, max_item)
var obj = {
offset: offset,
current_page: page,
per_page: per_page,
total: items.length,
total_pages: Math.ceil(items.length / per_page),
data: paginatedItems,
last: offset+paginatedItems.length,
max_item: max_item
}
this.pagination = obj
this.dados = this.pagination.data
},
Request who fill the data in vuex
axios
.get(`api/getusuariosgrupo/${id}`)
.then(res => {
if (res.data.dados !== undefined && res.data.dados.length !== 0){
vmThis.isEditing = true
var d = {
list: res.data.dados,
length: res.data.dados.length
}
this.$store.commit('SET_TABLE', d)
}else{
vmThis.isEditing = false
}
vmThis.$bus.$emit('processando',{val: false})
})