How to create array of sum of values in lodash - lodash

My data is
[
[{"2018":63},{"2019":28},{"2020":21}],
[{"2018":103},{"2019":200},{"2020":54}],
[{"2017":74},{"2019":76},{"2020":31}]
]
and I want array of sum of the values like
[112, 357, 181]
Thanks

Map the array. Flatten each sub-array to an array of values, and sum them:
const arr = [[{"2018":63},{"2019":28},{"2020":21}],[{"2018":103},{"2019":200},{"2020":54}],[{"2017":74},{"2019":76},{"2020":31}]]
const result = _.map(
arr,
s => _.sum(_.flatMap(s, _.values))
)
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>

Related

vuejs separate money with commas and periods

hello in vuejs I want to separate the amount of money with a comma and a period, how can I do it with filter?
I want the currency to be like this.
<p>1.000<span>,00</span></p>
I want the part separated by comma to be gray like in the image
Vue.filter('toTL', function (value) {
return new Intl.NumberFormat('tr-TR', { currency: 'TRY', minimumFractionDigits: 2}).format(value);
});
An easy solution would be to let the filter output the HTML:
<p class="amount" v-html="$options.filters.toTL(attributes.gross_total)" />
The filter can be written like so:
Vue.filter('toTL', function (value) {
let formatted = new Intl.NumberFormat('tr-TR', { currency: 'TRY', minimumFractionDigits: 2}).format(value);
let arr = formatted.split(',');
return arr[0] + '<span>,' + arr[1] + '</span>';
});
Links:
String.prototype.split documentation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
Also see this StackOverflow question:
VueJS2 v-html with filter

Am I overwriting computed property filter in Vue?

I am trying to create a reactive filter for an array in Vue. My starting array comes from an API call which returns this.features (geojson features). I am filtering on a nested array. This works -- but when I enter a search term and then backspace back out to an empty string, and enter another string, I am not filtering the original array but appear to be filtering the already-filtered array. How could I filter again on the original array from the API call?
computed property:
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return feature.properties.site_observations.length > 0
})
return filtered
}
I have looked at Vue filtering objects property but I cannot make that code work (it uses Object.assign()). Thanks for any ideas.
Your computed property is mutating feature.properties.site_observations, that's a nono. Computed properties should be read only.
filteredFeatures() {
if (this.searchTerm == '') {
return this.features
}
// filter on nested array
let filtered = this.features.filter(feature => {
const site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
return site_observations.length > 0
})
return filtered
}
It seems here is your problem:
feature.properties.site_observations = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Because this code filter feature and alter the proprieties of feature.properties.site_observations. Then, in the next read the value is alter. We say that your function it is not pure, because it alter the state of feature.
So, what you should do is:
let anotherVariable = feature.properties.site_observations.filter(
el => JSON.stringify(el).match(this.searchTerm, 'i')
)
Therefore, on a function, avoid alter state of objects, this lead to bugs.
On further checking, the above answer returns all site_observations, not just the ones that match the search. A much better solution is the following, using map to avoid overwriting the data, and the object spread operator to perform an object assign, and drilling down through the nested objects as follows:
filteredFeatures() {
return this.features
.map(feature => ({
...feature,
properties: {
site_observations: feature.properties.site_observations.filter(
element => {
return JSON.stringify(element).match(new RegExp(this.search, 'i'))
}
)
}
}))
.filter(feature => feature.properties.site_observations.length)
}

How can I rewrite pushing certain elements of a Javascript array into a new array in Lodash?

List item
I am trying to rewrite this specific logic from Javascript to
Lodash.
I want to try to stay away from using the push function, so that when
I create a new array with less element then the original array (only
copying certain elements of the array instead of the whole array)
then I will obtain the same result.
Here is an example in Javascript that I would like to rewrite in
Lodash
to avoid using push.the original example array would have more
key:value elments
```javascript
let exampleArray = {};
let newExampleArray = [];
for (var i = 0; i < this.exampleArray.length; i++) {
var feed = {
id: this.exampleArray[i].id,
field1: this.exampleArray[i].field1,
field2: this.exampleArray[i].field2,
field3: this.exampleArray[i].field3,
field4: this.exampleArray[i].field4,
sampleId: this.exampleArray[i].sampleId,
active: this.exampleArray[i].active
};
//Passing Json Feed into the new Array
newExampleArray.push(feed);
}
I have tried using push method in Javascript which worked. Lodash
functions map, reduce, spread, and compact did not work for me.
I'm not really sure what you are trying to do but...
exampleArray.forEach( ({ id, field1, field2, field3, field4, sampleId, active }) =>
newExampleArray.push({id, field1, field2, field3, field4, sampleId, active}));
same result in one line, or...
exampleArray.forEach( ({ unwantedField1, unwantedField2, ...rest }) => newExampleArray.push(rest));
or
newExampleArray = exampleArray.map(({ unwantedField1, unwantedField2, ...rest }) => rest )
all assuming that this exampleArray = {}; is a typo and meant let exampleArray = [];
This is all es6 js, no Lodash required

how to sum from array of object using lodash only?

hey I want to calculate the sum of one property from array of object using lodash
suppose the array of object looks like this ...
salary":[{
"bills":[{"electricity":300,"milk":500},
{"electricity":240,"milk":200},
{"electricity":800,"milk":900}]
}]
I want to calculate the sum of 'milk' from that object using lodash.
Use nested _.sumBy() calls. The internal gets the sum of milk from one salary, and the external sums all salaries:
const data = {"salary":[{"bills":[{"electricity":300,"milk":500},{"electricity":240,"milk":200},{"electricity":800,"milk":900}]}]}
const result = _.sumBy(data.salary, ({ bills }) => _.sumBy(bills, 'milk'))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Something like this
const bills = salary.map((s)=> s.bills)
_(bills).map((objs,key)=>({
'milk': _.sumBy(objs, 'milk')
})).value

Cakephp 3: view.ctp sum two variables

I have a view that shows an associated array of Revenues. I have made a collection in the controller to isolate two variables that I need to add together and display as currency.
public function view($id = null)
{
$annualOperatingBudget = $this->AnnualOperatingBudgets->get($id, [
'contain' => ['Azinstitutions', 'BudgetExpenses', 'BudgetExpenses.ExpenseTitles', 'BudgetRevenues', 'BudgetRevenues.RevenueTitles']
]);
$collection = new Collection($annualOperatingBudget->budget_revenues);
$revenuesGroup1 = $collection->match(['revenue_title.revenue_group' => 1 ]);
$revenuesGroup2 = $collection->match(['revenue_title.revenue_group' => 2 ]);
$tuitionAndFees = $collection->match(['revenue_title.revenue_title' => 'Tuition and Fees']);
$lessScholarshipAllowance = $collection->match(['revenue_title.revenue_title' => '- less Scholarship Allowance']);
$this->set(compact('annualOperatingBudget', $annualOperatingBudget,'revenuesGroup1', 'revenuesGroup2', 'tuitionAndFees', 'lessScholarshipAllowance'));
}
I am able to see the variables with the debug kit:
annualOperatingBudget (array)
revenuesGroup1 (array)
revenuesGroup2 (array)
tuitionAndFees (array)
4 (App\Model\Entity\BudgetRevenue)
id 5
annual_operating_budget_id 1
revenue 1278
revenue_title_id 5
revenue_title (array)
lessScholarshipAllowance (array)
5 (App\Model\Entity\BudgetRevenue)
id 6
annual_operating_budget_id 1
revenue -257
revenue_title_id 6
revenue_title (array)
I would like to add the two 'revenue' s together
I tried:
<?= $this->Number->currency(
($tuitionAndFees->revenue) + ($lessScholarShipAllowance->revenue),
'USD', ['places' => 1])
?>
But I get several errors:
Notice (8): Undefined property: Cake\Collection\Iterator\FilterIterator::$revenue [ROOT\plugins\Twit\src\Template\AnnualOperatingBudgets\view.ctp, line 49]
Notice (8): Undefined variable: lessScholarShipAllowance [ROOT\plugins\Twit\src\Template\AnnualOperatingBudgets\view.ctp, line 49]
Notice (8): Trying to get property of non-object [ROOT\plugins\Twit\src\Template\AnnualOperatingBudgets\view.ctp, line 49]
You have to iterate the $tuitionAndFees and the $lessScholarShipAllowance before trying to get the revenue property. Something like this:
foreach($tuitionAndFees as $tuitionAndFee){
echo $tuitionAndFee->revenue
}
If all you need in the view is the total of all tuition and fees, you can use
$tuitionAndFees = $collection
->match(['revenue_title.revenue_title' => 'Tuition and Fees'])
->sumOf('revenue');
This will return just the sum of the matched items. Do something similar for $lessScholarShipAllowance, and then in your view, simply
$this->Number->currency($tuitionAndFees + $lessScholarShipAllowance,
'USD', ['places' => 1])