Updating values of map using for in Clojure - vector

I have a json like below and have a requirement to add values in it
{ "10 days refund": [
{
"paymentType": "CreditCard",
"amount": "40$",
"expiryDate": "20/10/2025"
},
{
"paymentType": "CreditCard",
"amount": "20$",
"expiryDate": "20/1/2024"
}
],
"3 hours refund": [
{
"paymentType": "DebitCard",
"amount": "10$",
"expiryDate": "20/10/2026"
},
{
"paymentType": "DebitCard",
"amount": "5$",
"expiryDate": "20/10/2027"
}
]
}
In the above map, I would need to add a field "message" to last value of each category of map. So after adding the value I'm expecting the resultant map like below
{ "10 days refund": [
{
"paymentType": "CreditCard",
"amount": "40$",
"expiryDate": "20/10/2025"
},
{
"paymentType": "CreditCard",
"amount": "20$",
"expiryDate": "20/1/2024",
"message" : "Refund will be processed in 10 days"
}
],
"3 hours refund": [
{
"paymentType": "DebitCard",
"amount": "10$",
"expiryDate": "20/10/2026"
},
{
"paymentType": "DebitCard",
"amount": "5$",
"expiryDate": "20/10/2027",
"message" : "Refund will be processed in 3 hours"
}
]
}
I have tried implementing it using below method
(defn ^:private payment-methods
[pm-sorted]
(let [categories (group-by pm-fingerprint pm-sorted)]
(for [[pm-fingerprint pm-sorted] categories
:let [last-payment-method (last pm-sorted)
dropped-last (drop-last pm-sorted)]]
(if (= (:refund-category pm-fingerprint) "10 hours refund")
((println "10 days refund")
(doall (conj (doall dropped-last) (assoc last-payment-method :message
(text (str "Refund will be processed in 10 days"))))))
((println "3 hours refund")
(doall (conj (doall dropped-last) (assoc last-payment-method :message
(text (str "Refund will be processed in 3 hours"))))))))))
(defn ^:private pm-fingerprint
[payment-method]
(let [payment-type ("paymentType" payment-method)]
{:refund-category (if (= payment-type "CreditCard"))
"10 days refund"
"3 hours refund")}))
I expect the resultant output by executing the function to be a vector like below
[
{
"paymentType": "CreditCard",
"amount": "40$",
"expiryDate": "20/10/2025"
},
{
"paymentType": "CreditCard",
"amount": "20$",
"expiryDate": "20/1/2024",
"message" : "Refund will be processed in 10 days"
}
{
"paymentType": "DebitCard",
"amount": "10$",
"expiryDate": "20/10/2026"
},
{
"paymentType": "DebitCard",
"amount": "5$",
"expiryDate": "20/10/2027",
"message" : "Refund will be processed in 3 hours"
}
]
And I get null as the output as no value is returned. Can someone please help wrt the issue ?

Here is an example that works. First, declarations & data:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[schema.core :as s]
[tupelo.string :as str]
))
(def input
(str/quotes->double
"{ '10-days-refund': [
{ 'paymentType': 'CreditCard',
'amount': '40$',
'expiryDate': '20/10/2025' },
{ 'paymentType': 'CreditCard',
'amount': '20$',
'expiryDate': '20/1/2024' }
],
'3-hours-refund': [
{
'paymentType': 'DebitCard',
'amount': '10$',
'expiryDate': '20/10/2026' },
{ 'paymentType': 'DebitCard',
'amount': '5$',
'expiryDate': '20/10/2027' } ] }"))
Then the processing:
(dotest
(let [data (json->edn input)
data2 (vec
(for [entry data]
(let [[the-key pmt-lst] entry ; destruture into key and list of vals
pmt-lst-butlast (butlast pmt-lst)
pmt-lst-last (last pmt-lst)
last-new (assoc pmt-lst-last :message "Coming Soon!")
pmt-lst-new (append pmt-lst-butlast last-new)
entry-new [the-key pmt-lst-new]]
entry-new)))]
and the result verified:
(is= data2
[[:10-days-refund
[{:amount "40$" :expiryDate "20/10/2025" :paymentType "CreditCard"}
{:amount "20$"
:expiryDate "20/1/2024"
:message "Coming Soon!"
:paymentType "CreditCard"}]]
[:3-hours-refund
[{:amount "10$" :expiryDate "20/10/2026" :paymentType "DebitCard"}
{:amount "5$"
:expiryDate "20/10/2027"
:message "Coming Soon!"
:paymentType "DebitCard"}]]]
)))
Please see the list of documentation in this template project, especially the Clojure CheatSheet.

Related

How to get sum of value from Json Array in Vue

My json array is
"test": [
{
"name": "item1",
"value": "440"
},
{
"name": "item2",
"value": "220"
},
{
"name": "item3",
"value": "46"
}
]
I'm calling function from template as
<template>
<td>{{ calculateSumofValues(test) }}</td>
</template>
Script function is
<script setup lang="ts">
const calculateSumofValues = (test?:Object) => {
console.log("test", test)
// calculate sum of values
};
</script>
I want to calculate total values of every item on the array (440+220+46 = 706)
Please help me to solve this issue.
You could use reduce() function to do something over every element in an array and accumulate results somehow, useful for summing over values in the array.
const test = [{
"name": "item1",
"value": "440"
},
{
"name": "item2",
"value": "220"
},
{
"name": "item3",
"value": "46"
}
]
const calculateSumofValues = (test) => {
console.log("test", test)
return test.reduce((acc, cur) => acc + parseInt(cur.value), 0)
};
console.log(calculateSumofValues(test))

jq element matching with in a nested array

I have an array of array as following
[
{
"devices": [
{
"files": [
{
"id": "2",
"type": "file"
}
],
"path": "/tmp/file1"
},
{
"files": [
{
"id": "3",
"type": "file"
}
],
"path": "/tmp/file2"
}
],
"name": "a"
},
{
"devices": [
{
"files": [
{
"id": "4",
"type": "file"
}
],
"path": "/tmp/tfile"
},
{
"files": [
{
"id": "5",
"type": "file"
}
],
"path": "/var/mfile"
}
],
"name": "b"
}
]
I'm looking for output like this
a /tmp/file1 2
a /tmp/file2 3
b /tmp/tfile 4
b /var/mfile 5
What I have tried
cat myfile.json | jq '.[] | "\(.name), \(.devices[].path) \(.devices[].files[].id)"'
and result is
"a, /tmp/file1 2"
"a, /tmp/file2 2"
"a, /tmp/file1 3"
"a, /tmp/file2 3"
"b, /tmp/tfile 4"
"b, /var/mfile 4"
"b, /tmp/tfile 5"
"b, /var/mfile 5"
but I'm unable to select a key for the value is in parent map.
I want to for each of the elements matching name == a, for each of a[path], get a[path][id].
Using .devices[] twice will iterate over the same .devices twice, giving you the cartesian product. Extract from within one iteration.
You can nest string iterpolation; otherwise collect into an array (here you'd need , as separator) and use join(" ") to concatenate
Use the -r (or --raw-output) flag to output raw text
jq -r '.[] | "\(.name) \(.devices[] | "\(.path) \(.files[].id)")"'
a /tmp/file1 2
a /tmp/file2 3
b /tmp/tfile 4
b /var/mfile 5
Demo

Is there any function that is used to decrease the date by year when the key has null value

FOllowing is the input that i have
[{
"date": " "
},
{
"date": "2022-01-21"
},{
"date": " "
},{
"date": " "
},{
"date": " "
}]
And the required output is as follows
[
{
"Date": "2022-01-21"
},
{
"Date": "2021-01-21"
},
{
"Date": "2020-01-21"
},
{
"Date": "2019-01-21"
},
{
"Date": "2018-01-21"
}
]
Thanks in advance!!
It should be obvious that there is no buil-in function in DataWeave to achieve this result. You can create a custom function for it. For example using a recursive function we can get the expected output from your input:
%dw 2.0
output application/json
fun decDates(a, nextDate)=
[{date: nextDate}]
++
if (sizeOf(a) > 1) decDates(dw::core::Arrays::drop(a, 1), nextDate - |P1Y|) else []
---
decDates(payload, |2022-03-21|)
Output:
[
{
"date": "2022-03-21"
},
{
"date": "2021-03-21"
},
{
"date": "2020-03-21"
},
{
"date": "2019-03-21"
},
{
"date": "2018-03-21"
}
]

CosmosDB, help flatten an array

I'm trying to flatten and filter my json data that is in a CosmosDB. The data looks like below and I would like to flatten everything in the array Variables. I need to show the id, amount and the array of orderidentifiers( only the orderId field)
my json:
{
"id": "b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3",
"amount": 5354.39,
"orderIdentifiers": [
{
"orderId": "16520328183646646587",
"itemIds": [
"90420839-2769-3acc-a686-3171386190a7"
]
},
{
"orderId": "45288779686596595261",
"itemIds": [
"fb662e41-1c7e-3f36-8cfd-ef2f3c7f0752",
"0b97371c-4eb9-3ec5-8ab9-bb65a9c9efe1"
]
},
{
"orderId": "859986489484974993023",
"itemIds": [
"5c16bb0d-f1a4-3289-bda5-28d0b09a2a56",
"ffb5dc2a-6e43-321d-97cb-3279ddfd1e39",
"781953ad-83e0-30da-a563-e69ed2a752c6",
"1936e885-c41a-3bd1-a3e0-80e7e3089fe4"
]
},
{
"orderId": "80455639909013091834",
"itemIds": [
"147d4a11-6c05-3fe3-8e4c-bcda3d238845",
"6c586585-6355-393d-a6f4-6fa6c665f3b8"
]
}
]
}
when I run this query :
select c.id, c.amount, oi.orderId
from finalcategorysales c
JOIN oi IN c.orderIdentifiers
where c.id='b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3'
the result is showing me only one element in orderIdentifiers array
{ "id": "b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3",
"amount": 5354.39,
"orderId": "16520328183646646587"
},
You can try something like this SQL:
SELECT
c.id, c.amount, Array(SELECT oi.orderId FROM c JOIN oi IN c.orderIdentifiers) AS orderIds
FROM c
WHERE c.id='b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3'
Result:
[
{
"id": "b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3",
"amount": 5354.39,
"orderIds": [
{
"orderId": "16520328183646646587"
},
{
"orderId": "45288779686596595261"
},
{
"orderId": "859986489484974993023"
},
{
"orderId": "80455639909013091834"
}
]
}
]

filter nest tree object by object id

I have a tree object like below:
let data = [
{
id: 1,
children: [
{
id: 1.1,
children: [
{
id: 1.2,
children: []
},
{
id: 1.22,
children: []
}
]
}
]
},
{
id: 2,
children: []
}
]
I want to filter out id equal a specific value. In this case, I want to filter out id equal 1.2.
The rusult I want is like below:
let data = [
{
id: 1,
children: [
{
id: 1.1,
children: [
{
id: 1.22,
children: []
}
]
}
]
},
{
id: 2,
children: []
}
]
I have search a few question about filter nest deep object, But still don't know how. I need to use recursion to solve this.
This is my way:
function handleDelete (data) {
return data.filter(t => {
if (t.children.length) {
handleDelete(t.children)
})
} else {
return t.id !== '1.2'
}
})
}
let result = handleDelete(data)
delete a node and its descendants
Here's an effective technique using flatMap and mutual recursion1 -
del accepts an array of nodes, t, a query, q, and calls del1 on each node with the query
del1 accepts a single node, t, a query, q, and calls del on a node's children
const del = (t, q) =>
t.flatMap(v => del1(v, q)) // <-- 1
const del1 = (t, q) =>
q == t.id
? []
: { ...t, children: del(t.children, q) } // <-- 2
const data =
[{id:1,children:[{id:1.1,children:[{id:1.2,children:[]},{id:1.22,children:[]}]}]},{id:2,children:[]}]
const result =
del(data, "1.2")
console.log(result)
In the output, we see node.id 1.2 is removed -
[
{
"id": 1,
"children": [
{
"id": 1.1,
"children": [
{
"id": 1.22,
"children": []
}
]
}
]
},
{
"id": 2,
"children": []
}
]
preserving the descendants
In the program above, if a node.id matches our query, the node and all of its descendent children are removed. If we only want to delete the parent node and keep the children, we can make a single modification (!) to the program -
const del = (t, q) =>
t.flatMap(v => del1(v, q))
const del1 = (t, q) =>
q == t.id
? del(t.children, q) // <-- !
: { ...t, children: del(t.children, q) }
const data =
[{id:1,children:[{id:1.1,children:[{id:1.2,children:[]},{id:1.22,children:[]}]}]},{id:2,children:[]}]
const result =
del(data, "1") // <-- delete node.id equal to "1"
console.log(result)
Notice how the children for 1 are still included in the output -
[
{
"id": 1.1,
"children": [
{
"id": 1.2,
"children": []
},
{
"id": 1.22,
"children": []
}
]
},
{
"id": 2,
"children": []
}
]
without mutual recursion
Mutual recursion isn't the only way to do it, but it's the only way to avoid a dynamic type check, such as the one below. In this final revision, we remove a parent and all of its children, as we did in the first program, but this del is implemented using a single recursive function -
const del = (t, q) =>
Array.isArray(t) // <-- array
? t.flatMap(v => del(v, q))
: Object(t) === t // <-- object
? q == t.id
? []
: { ...t, children: del(t.children, q) }
: t // <-- neither (noop)
const data =
[{id:1,children:[{id:1.1,children:[{id:1.2,children:[]},{id:1.22,children:[]}]}]},{id:2,children:[]}]
const result =
del(data, "1.2")
console.log(result)
The output is the same as the first program, where 1.2 and all descendants are removed -
[
{
"id": 1,
"children": [
{
"id": 1.1,
"children": [
{
"id": 1.22,
"children": []
}
]
}
]
},
{
"id": 2,
"children": []
}
]
1. See this technique used on a different data set in this related Q&A.
2. All programs in this answer produce a new tree. The original input is not modified by del (or del1).

Resources