Merging arrays of dictionaries based on dates
I have 2 arrays, both of kind [[String:Any]]
, where each element :
["date":Date,"value":CGFloat] //always looks like this
I might even have more than 2 (!)
I would like to create a single array with the same structure that sums all of them (2 or more) for each date that appears in all of them.
If the date of array1 does not appear on the others(array2, etc) I will simply add 0 to the value at array 1 for this specific date.
Is there a simple efficient way to do so ?
arrays swift dictionary
add a comment |
I have 2 arrays, both of kind [[String:Any]]
, where each element :
["date":Date,"value":CGFloat] //always looks like this
I might even have more than 2 (!)
I would like to create a single array with the same structure that sums all of them (2 or more) for each date that appears in all of them.
If the date of array1 does not appear on the others(array2, etc) I will simply add 0 to the value at array 1 for this specific date.
Is there a simple efficient way to do so ?
arrays swift dictionary
Can you give an example? You keep saying array here and there, but all i can visualize is just two dictionaries.
– Rakesha Shastri
Nov 25 '18 at 9:12
[[String:Any]] is not a dictionary, its an array of dics...
– Curnelious
Nov 25 '18 at 9:22
Ok, please show us your use case with an example.
– Rakesha Shastri
Nov 25 '18 at 9:25
When you say “more than 2”, do you mean two keys in the dictionary or two elements in the array?
– Carpsen90
Nov 25 '18 at 9:44
I mean more arrays , say to sum 6 arrays by dates:)
– Curnelious
Nov 25 '18 at 9:46
add a comment |
I have 2 arrays, both of kind [[String:Any]]
, where each element :
["date":Date,"value":CGFloat] //always looks like this
I might even have more than 2 (!)
I would like to create a single array with the same structure that sums all of them (2 or more) for each date that appears in all of them.
If the date of array1 does not appear on the others(array2, etc) I will simply add 0 to the value at array 1 for this specific date.
Is there a simple efficient way to do so ?
arrays swift dictionary
I have 2 arrays, both of kind [[String:Any]]
, where each element :
["date":Date,"value":CGFloat] //always looks like this
I might even have more than 2 (!)
I would like to create a single array with the same structure that sums all of them (2 or more) for each date that appears in all of them.
If the date of array1 does not appear on the others(array2, etc) I will simply add 0 to the value at array 1 for this specific date.
Is there a simple efficient way to do so ?
arrays swift dictionary
arrays swift dictionary
asked Nov 25 '18 at 8:55
CurneliousCurnelious
3,857750102
3,857750102
Can you give an example? You keep saying array here and there, but all i can visualize is just two dictionaries.
– Rakesha Shastri
Nov 25 '18 at 9:12
[[String:Any]] is not a dictionary, its an array of dics...
– Curnelious
Nov 25 '18 at 9:22
Ok, please show us your use case with an example.
– Rakesha Shastri
Nov 25 '18 at 9:25
When you say “more than 2”, do you mean two keys in the dictionary or two elements in the array?
– Carpsen90
Nov 25 '18 at 9:44
I mean more arrays , say to sum 6 arrays by dates:)
– Curnelious
Nov 25 '18 at 9:46
add a comment |
Can you give an example? You keep saying array here and there, but all i can visualize is just two dictionaries.
– Rakesha Shastri
Nov 25 '18 at 9:12
[[String:Any]] is not a dictionary, its an array of dics...
– Curnelious
Nov 25 '18 at 9:22
Ok, please show us your use case with an example.
– Rakesha Shastri
Nov 25 '18 at 9:25
When you say “more than 2”, do you mean two keys in the dictionary or two elements in the array?
– Carpsen90
Nov 25 '18 at 9:44
I mean more arrays , say to sum 6 arrays by dates:)
– Curnelious
Nov 25 '18 at 9:46
Can you give an example? You keep saying array here and there, but all i can visualize is just two dictionaries.
– Rakesha Shastri
Nov 25 '18 at 9:12
Can you give an example? You keep saying array here and there, but all i can visualize is just two dictionaries.
– Rakesha Shastri
Nov 25 '18 at 9:12
[[String:Any]] is not a dictionary, its an array of dics...
– Curnelious
Nov 25 '18 at 9:22
[[String:Any]] is not a dictionary, its an array of dics...
– Curnelious
Nov 25 '18 at 9:22
Ok, please show us your use case with an example.
– Rakesha Shastri
Nov 25 '18 at 9:25
Ok, please show us your use case with an example.
– Rakesha Shastri
Nov 25 '18 at 9:25
When you say “more than 2”, do you mean two keys in the dictionary or two elements in the array?
– Carpsen90
Nov 25 '18 at 9:44
When you say “more than 2”, do you mean two keys in the dictionary or two elements in the array?
– Carpsen90
Nov 25 '18 at 9:44
I mean more arrays , say to sum 6 arrays by dates:)
– Curnelious
Nov 25 '18 at 9:46
I mean more arrays , say to sum 6 arrays by dates:)
– Curnelious
Nov 25 '18 at 9:46
add a comment |
2 Answers
2
active
oldest
votes
Instead of dictionaries use structs, it's more convenient:
struct MyStruct {
let date: Date
let value: CGFloat
}
Let's create 3 arrays of MyStruct
s:
let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)
let array1: [MyStruct] = [MyStruct(date: now, value: 1),
MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
MyStruct(date: later, value: 6)]
Now, let's group the elements and add the value
s for the elements with the same date
property:
let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
uniquingKeysWith: { $0 + $1 })
All you have to do now is convert it back to an array of MyStruct
:
let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }
And you can check the results like so:
for element in newArray {
print("date =", element.date, "value =", element.value)
}
add a comment |
I found a way, assuming data is inside a structure(not a dic) which is a better practice.
I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.
//create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}
//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }
//new array - sum of all
var sumData = [RootData]()
var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))
return averageData
Here RootData
is a simple structure for the data with :
value:CGFloat
date:Date
Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53465993%2fmerging-arrays-of-dictionaries-based-on-dates%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Instead of dictionaries use structs, it's more convenient:
struct MyStruct {
let date: Date
let value: CGFloat
}
Let's create 3 arrays of MyStruct
s:
let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)
let array1: [MyStruct] = [MyStruct(date: now, value: 1),
MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
MyStruct(date: later, value: 6)]
Now, let's group the elements and add the value
s for the elements with the same date
property:
let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
uniquingKeysWith: { $0 + $1 })
All you have to do now is convert it back to an array of MyStruct
:
let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }
And you can check the results like so:
for element in newArray {
print("date =", element.date, "value =", element.value)
}
add a comment |
Instead of dictionaries use structs, it's more convenient:
struct MyStruct {
let date: Date
let value: CGFloat
}
Let's create 3 arrays of MyStruct
s:
let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)
let array1: [MyStruct] = [MyStruct(date: now, value: 1),
MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
MyStruct(date: later, value: 6)]
Now, let's group the elements and add the value
s for the elements with the same date
property:
let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
uniquingKeysWith: { $0 + $1 })
All you have to do now is convert it back to an array of MyStruct
:
let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }
And you can check the results like so:
for element in newArray {
print("date =", element.date, "value =", element.value)
}
add a comment |
Instead of dictionaries use structs, it's more convenient:
struct MyStruct {
let date: Date
let value: CGFloat
}
Let's create 3 arrays of MyStruct
s:
let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)
let array1: [MyStruct] = [MyStruct(date: now, value: 1),
MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
MyStruct(date: later, value: 6)]
Now, let's group the elements and add the value
s for the elements with the same date
property:
let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
uniquingKeysWith: { $0 + $1 })
All you have to do now is convert it back to an array of MyStruct
:
let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }
And you can check the results like so:
for element in newArray {
print("date =", element.date, "value =", element.value)
}
Instead of dictionaries use structs, it's more convenient:
struct MyStruct {
let date: Date
let value: CGFloat
}
Let's create 3 arrays of MyStruct
s:
let now = Date()
let later = now.addingTimeInterval(3600)
let earlier = now.addingTimeInterval(-3600)
let array1: [MyStruct] = [MyStruct(date: now, value: 1),
MyStruct(date: later, value: 2)]
let array2: [MyStruct] = [MyStruct(date: now, value: 3),
MyStruct(date: later, value: 4)]
let array3: [MyStruct] = [ MyStruct(date: earlier, value: 5),
MyStruct(date: later, value: 6)]
Now, let's group the elements and add the value
s for the elements with the same date
property:
let allArrays = array1 + array2 + array3
let dict = Dictionary(allArrays.map { ($0.date, $0.value) },
uniquingKeysWith: { $0 + $1 })
All you have to do now is convert it back to an array of MyStruct
:
let newArray = dict.map { MyStruct(date: $0.key, value: $0.value) }
And you can check the results like so:
for element in newArray {
print("date =", element.date, "value =", element.value)
}
answered Nov 25 '18 at 14:45
Carpsen90Carpsen90
7,46262659
7,46262659
add a comment |
add a comment |
I found a way, assuming data is inside a structure(not a dic) which is a better practice.
I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.
//create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}
//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }
//new array - sum of all
var sumData = [RootData]()
var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))
return averageData
Here RootData
is a simple structure for the data with :
value:CGFloat
date:Date
Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.
add a comment |
I found a way, assuming data is inside a structure(not a dic) which is a better practice.
I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.
//create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}
//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }
//new array - sum of all
var sumData = [RootData]()
var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))
return averageData
Here RootData
is a simple structure for the data with :
value:CGFloat
date:Date
Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.
add a comment |
I found a way, assuming data is inside a structure(not a dic) which is a better practice.
I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.
//create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}
//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }
//new array - sum of all
var sumData = [RootData]()
var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))
return averageData
Here RootData
is a simple structure for the data with :
value:CGFloat
date:Date
Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.
I found a way, assuming data is inside a structure(not a dic) which is a better practice.
I will put all arrays into a single large array, sort it by dates, loop on it and as long as date is equal previous date(or close enough to equality), I will sum the values up. When the next date is different, I will save the date and the sum.
//create a combined array from all given arrays
var combined = [RootData]()
for list in dataSets {combined.append(contentsOf: list)}
//sort it by dates
let sortedArray = combined.sorted { $0.date < $1.date }
//new array - sum of all
var sumData = [RootData]()
var last:Date = sortedArray[0].date //set starting point
var sum:CGFloat = 0
for element in sortedArray
{
//same date - accumulate(same is less than 1 sec difference)
if(abs(element.date.seconds(from: last)) <= 1) {
sum+=element.value
}
//save
else {
sumData.append(RootData(value:sum,date:last))
sum=element.value
}
last=element.date
}
//last object
sumData.append(RootData(value:sum,date:last))
return averageData
Here RootData
is a simple structure for the data with :
value:CGFloat
date:Date
Works as expected.
Because dates are not always completely equal , I check equality by assuming 1 second or less is the same date.
edited Nov 26 '18 at 2:30
answered Nov 25 '18 at 16:06
CurneliousCurnelious
3,857750102
3,857750102
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53465993%2fmerging-arrays-of-dictionaries-based-on-dates%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can you give an example? You keep saying array here and there, but all i can visualize is just two dictionaries.
– Rakesha Shastri
Nov 25 '18 at 9:12
[[String:Any]] is not a dictionary, its an array of dics...
– Curnelious
Nov 25 '18 at 9:22
Ok, please show us your use case with an example.
– Rakesha Shastri
Nov 25 '18 at 9:25
When you say “more than 2”, do you mean two keys in the dictionary or two elements in the array?
– Carpsen90
Nov 25 '18 at 9:44
I mean more arrays , say to sum 6 arrays by dates:)
– Curnelious
Nov 25 '18 at 9:46