Remove common elements from JSON Objects in Array - arrays

I have an array of objects and I am looking to remove all the elements from the objects and their sub-objects that are common across all objects.
Maybe the best way to explain this is with an example
[
{
"a": {
"k1": [1,2,3],
"k2": 4
},
"b": {
"k3": {
"foo": "bar",
"top": "bottom"
},
"k4": 5
},
"c": {
"k5": [{"cat":"dog"},{"rat":"not rat"}]
},
"d": { }
},
{
"a": {
"k1": [1,2,3],
"k2": -4
},
"b": {
"k3": {
"foo": "hat",
"top": "bottom"
},
"k4": 5
},
"c": {
"k5": [{"cat":"dog"},{"rat":"mouse"}]
}
}
]
would evaluate to
[
{
"a": {
"k2": 4
},
"b": {
"k3": {
"foo": "bar"
}
},
"c": {
"k5": [{"cat":"dog"},{"rat":"not rat"}]
},
"d": { }
},
{
"a": {
"k2": -4
},
"b": {
"k3": {
"foo": "hat"
}
},
"c": {
"k5": [{"cat":"dog"},{"rat":"mouse"}]
},
"d": null
}
]
Are there any good tools I can use to solve this? I looked at json-diff but that doesn't quite fit my requirements.

I wrote some julia functions to do this for me
I started by computing the common fields in the objects and then proceeded to remove the common fields from each of the objects.
function common_in_array(a::Array)
common = deepcopy(a[end])
common_in_array!(a[1:end-1], common)
end
function common_in_array!(a::Array, common::Dict)
if size(a,1) == 0
return common
else
return common_in_array!(a[1:end-1], dict_common!(a[end], common))
end
end
function dict_common!(d::Dict, common::Dict)
keys_d = keys(d)
keys_common = keys(common)
all_keys = union(keys_d, keys_common)
and_keys = intersect(keys_d, keys_common)
for k in setdiff(all_keys, and_keys)
delete!(common, k)
end
for k in and_keys
v1 = d[k]
v2 = common[k]
if typeof(v1) != typeof(v2)
delete!(common, k)
elseif isa(v2, Dict)
dict_common!(v1, v2)
elseif v1 != v2
delete!(common, k)
end
end
common
end
function remove_common_from_dict!(d::Dict, common::Dict)
for (key, value) in common
if key in keys(d)
value_d = d[key]
if value == value_d
delete!(d, key)
elseif isa(value, Dict) && isa(value_d, Dict)
remove_common_from_dict!(value_d, value)
end
end
end
d
end
function remove_common_from_array!(a::Array, common::Dict)
map(d -> remove_common_from_dict!(d, common), a)
end
function remove_common_from_array!(a::Array)
remove_common_from_array!(a, common_in_array(a))
end
then I evaluate this on my json_array string
using JSON
JSON.print(remove_common_from_array!(JSON.parse(json_array)))

Related

Calculation on dynamic data in React

This array can be fetched by .map in return()
[
{
"a": "3",
"Count": "3",
"b": "299.98999786376953",
"c": "30",
"d": "30"
},
{
"a": "9",
"Count": "1",
"b": "99.98999786376953",
"c": "10",
"d": "9"
}
]
I want to apply formulas on it like:
a = a/Count;
b = (b/(Count*10))*100;
c = (c/(Count*10))*100;
d = (d/(Count*10))*100;
Also find e = (a+b+c+d)/4;
then display them in each table row's data using .map
I tried npmjs.com/package/react-equation, it can do calculations directly in return() however don't fetch dynamic variables of array inside return(). I also tried creating a function outside return add(a,b){return a+b) and calling it inside return(), neither do it work and tried some other methods as well.
Here is a sample code that can help you continue your work. It uses map to transform your string array to float array and also return the new calculated objects
const array = [
{
"a": "3",
"Count": "3",
"b": "299.98999786376953",
"c": "30",
"d": "30"
},
{
"a": "9",
"Count": "1",
"b": "99.98999786376953",
"c": "10",
"d": "9"
}
]
const newArray = array.map(obj => {
const a = parseFloat(obj.a) / parseFloat(obj.Count);
const b = (parseFloat(obj.b)/(parseFloat(obj.Count) * 10)) * 100
const c = (parseFloat(obj.c)/(parseFloat(obj.Count) * 10)) * 100
const d = (parseFloat(obj.d)/(parseFloat(obj.Count) * 10)) * 100
return { a, b, c, d, e: (a+b+c+d)/4}
})
console.log(array, newArray)
I don't think you can really use map because you're doing different calculations for a and for b,c,d and for e, and also because the calcultions on a depends on value of Count. You could just define a function that accepts the entire object and performs the calculations like so:
const performCalculations = (obj) => {
obj.a = obj.a / obj.Count;
obj.b = (obj.b/(obj.Count*10))*100;
obj.c = (obj.c/(obj.Count*10))*100;
obj.d = (obj.d/(obj.Count*10))*100;
obj.e = (obj.a + obj.b + obj.c + obj.d)/4;
return obj;
}
Edit: you can use map see #Apostolos answer

How to compare list of array to another array using typescript

i have a list of array and a single array. I want to compare this 2 array like this if productID and attributesData match return something my list structure given below
List1:
{
"unitPrice": "800.0",
"productTypeTitle": "TYPE",
"productId": "470",
"attributesData": [
{
"attributeName": "COLOR",
"attributeData": "BLUE"
},
{
"attributeName": "SIZE",
"attributeData": "36"
},
{..}
],
"count": 2,
"shopid": "53",
"sessionid": "1643195257593",
...
},
{
},...
]
List2:
{
"unitPrice": "800.0",
"productTypeTitle": "TYPE",
"productId": "470",
"attributesData": [
{
"attributeName": "SIZE",
"attributeData": "42"
},
{
"attributeName": "COLOR",
"attributeData": "Orange"
},{...}
]
...
}
Here productId is same but attributesData not same how can I find out that.I am able check if productId is same or not but unable to compare attributesData .How I can solve this problem of efficient way
You can use lodash isEqual, https://docs-lodash.com/v4/is-equal/
function isEqual(list1,list2):boolean{
return isEqual(list1,list2)
}
if not using lodash
-then you need to cycle through all the properties and compare
function deepEqual(a, b) {
if (a === b) {
return true;
}
if (a == null || typeof(a) != "object" ||
b == null || typeof(b) != "object")
{
return false;
}
var propertiesInA = 0, propertiesInB = 0;
for (var property in a) {
propertiesInA += 1;
}
for (var property in b) {
propertiesInB += 1;
if (!(property in a) || !deepEqual(a[property], b[property])) {
return false;
}
}
return propertiesInA == propertiesInB;
}
this link source
enter link description here
because object is reference when process equaling

How to filter a nested array of dictionaries with multiple conditions from another array in Swift

sample json data is this:
{
"variations": [
{
"variation_id": 391,
"name": "Fruit Shake - Chocolate, S",
"price": 10,
"attribute": [
{
"attribute_key": "pa_flavor",
"name": "Flavor",
"option": "Chocolate"
},
{
"attribute_key": "pa_size",
"name": "Size",
"option": "S"
}
]
},
{
"variation_id": 385,
"name": "Fruit Shake - Banana, L",
"price": 18,
"attribute": [
{
"attribute_key": "pa_flavor",
"name": "Flavor",
"option": "Banana"
},
{
"attribute_key": "pa_size",
"name": "Size",
"option": "L"
}
]
},
{
"variation_id": 386,
"name": "Fruit Shake - Banana, M",
"price": 15,
"attribute": [
{
"attribute_key": "pa_flavor",
"name": "Flavor",
"option": "Banana"
},
{
"attribute_key": "pa_size",
"name": "Size",
"option": "M"
}
]
}
]
}
my problem is, getting the variation_id where 2 or more attributes matches the array of string.
for example, chosenProduct = ["Banana", "L"]
I tried filter and contains but theres no way to match the other item from chosenProduct.
If I added the next condition, it returns nil
You can try this:
let varID = product.variations?.filter { att in
var matchedAttributes = 0
for thisAttribute in att.attribute {
if chosenProduct.contains(where: {$0 == thisAttribute.option}) {
matchedAttributes += 1
}
}
if matchedAttributes >= 2 {
return true
}
return false
}
Let me know if there's any doubt.
You can try this :
var chosenProduct = ["Banana","L"]
var expectedIds : [Int] = [Int]()
datas.variations?.map{ val in
val.attribute.map({ val2 in
let filtered = val2.enumerated().filter({chosenProduct.contains($0.element.option!)})
if filtered.count == chosenProduct.count{
expectedIds.append(val.variation_id!)
}
})
}
print(expectedIds) // [385]
I put the id's in array because of if you want to change your chosenProcudt example "Banana" (count 1 ). This mapping must be return variation_id like [385,386]
You can a method to Variation to make things easier:
extension Variation {
func attributesMatching(options: [String]) -> [Attribute] {
attribute.filter { options.contains($0.option) }
}
}
Then, you can just write:
let filtered = product.variations.filter { $0.attributesMatching(options: chosenProductOptions).count >= 2 }
print(filtered.map { $0.variationID })

In MongoDB, how to Update an Array in an Object in a Document

My Document looks like this in MongoDB:
{
"_id": {
"$oid": "6099d057b769cc513025fd54"
},
"key_name": "I_CAN_MATCH",
"object_1": {
"sub_object_array_1": [{
"a": "TZNNI",
"b": "R"
}],
"sub_object_array_2": [{
"c": "SDLYA",
"d": "N"
}, {
"c": "KTSMQ",
"d": "N"
}],
"sub_object_array_3": [{
"e": "KYCT0",
"f": "F"
}, {
"e": "KYCT1",
"f": "N"
}, {
"e": "KYCT2",
"f": "F"
}, {
"e": "KYCT3",
"f": "E"
}],
},
"object_2": {
"sub_object_4": { "and": "so on ..." }
},
"object_array_1": [{
"g": "KYCT0",
"h": "F"
}, {
"g": "KYCT1",
"h": "N"
}, {
"g": "KYCT2",
"h": "F"
}, {
"g": "KYCT3",
"h": "E"
}]
}
My question is how to Update Array sub_object_array_3 where f = "F" to f = "U"?
The following does not work for me:
await db_model.updateMany(
{ key_name: "I_CAN_MATCH" },
{ $set: { "object_1.sub_object_array_3.$[array_element].f": "U" } },
{ arrayFilters: [ { "array_element.f": "F" } ] } );
But the following does! So I understand how the syntax works in this scenario.
await db_model.updateMany(
{ key_name: "I_CAN_MATCH" },
{ $set: { "object_array_1.$[array_element].h": "U" } },
{ arrayFilters: [ { "array_element.h": "F" } ] } );
I just don't know what I'm missing in the $set command when the Array is inside an Object first.
I have searched, but every search word I use points me to arrays in arrays, which is not the case here.
Is anyone able to help me?
Thanks in advance!
Error - https://mongoplayground.net/p/Cvfc6oNyhrH
fail to run update: multiple write errors: [{write errors: [{Error parsing array filter :: caused by :: The top-level field name must be an alphanumeric string beginning with a lowercase letter, found 'array_element'}]}, {<nil>}]
Solution :-
Change array_element to arrayElement or anything without _
Note:- it should be alphanumeric
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/
The must begin with a lowercase letter and contain only alphanumeric characters.
Demo - https://mongoplayground.net/p/GJku1bFaj3m
db.collection.update({
key_name: "I_CAN_MATCH"
},
{
$set: {
"object_1.sub_object_array_3.$[arrayElement].f": "U"
}
},
{
arrayFilters: [
{ "arrayElement.f": "F" }
]
})

How value become value as an key in MonogoDB array?

Explanation :
I want to convert the value as part of the key, in document 1 "xyz" replace with v and in document 2, "abc" replace with v.
Note: there are multiple documents, which I don't know what could be the document 3 "sig_nam" value.
Doc No. 1
"sig_nam": "xyz",
"cont_name": "1",
"t_v": [
{
"t": "2020-11-20T03:00",
"v": 0
},
{
"t": "2020-10-25T03:00",
"v": 0
}
]
}
Doc No. 2
{
"sig_nam": "abc",
"cont_name": "1",
"t_v": [
{
"t": "2020-11-20T03:00",
"v": 0
},
{
"t": "2020-10-25T03:00",
"v": 0
}
]
}
Expected Output Doc No. 1
"sig_nam": "xyz",
"cont_name": "1",
"t_v": [
{
"t": "2020-11-20T03:00",
"xyz": 0
},
{
"t": "2020-10-25T03:00",
"xyz": 0
}
]
}
Expected Output Doc No. 2
{
"sig_nam": "abc",
"cont_name": "1",
"t_v": [
{
"t": "2020-11-20T03:00",
"abc": 0
},
{
"t": "2020-10-25T03:00",
"abc": 0
}
]
}
$map to iterate loop of t_v array
$arrayToObject, set k as sig_nam and v as count and same for t, wrap in to an array bracket, it will convert in to object
db.collection.aggregate([
{
$addFields: {
t_v: {
$map: {
input: "$t_v",
in: {
$arrayToObject: [[
{ k: "t", v: "$$this.t" },
{ k: "$sig_nam", v: "$$this.v" }
]]
}
}
}
}
}
])
Playground

Resources