Merging arrays of dictionaries based on dates












1















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 ?










share|improve this question























  • 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
















1















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 ?










share|improve this question























  • 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














1












1








1








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 ?










share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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



















  • 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












2 Answers
2






active

oldest

votes


















1














Instead of dictionaries use structs, it's more convenient:



struct MyStruct {
let date: Date
let value: CGFloat
}


Let's create 3 arrays of MyStructs:



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 values 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)
}





share|improve this answer































    0














    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.






    share|improve this answer

























      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
      });


      }
      });














      draft saved

      draft discarded


















      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









      1














      Instead of dictionaries use structs, it's more convenient:



      struct MyStruct {
      let date: Date
      let value: CGFloat
      }


      Let's create 3 arrays of MyStructs:



      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 values 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)
      }





      share|improve this answer




























        1














        Instead of dictionaries use structs, it's more convenient:



        struct MyStruct {
        let date: Date
        let value: CGFloat
        }


        Let's create 3 arrays of MyStructs:



        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 values 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)
        }





        share|improve this answer


























          1












          1








          1







          Instead of dictionaries use structs, it's more convenient:



          struct MyStruct {
          let date: Date
          let value: CGFloat
          }


          Let's create 3 arrays of MyStructs:



          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 values 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)
          }





          share|improve this answer













          Instead of dictionaries use structs, it's more convenient:



          struct MyStruct {
          let date: Date
          let value: CGFloat
          }


          Let's create 3 arrays of MyStructs:



          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 values 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)
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 25 '18 at 14:45









          Carpsen90Carpsen90

          7,46262659




          7,46262659

























              0














              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.






              share|improve this answer






























                0














                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.






                share|improve this answer




























                  0












                  0








                  0







                  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.






                  share|improve this answer















                  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.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 26 '18 at 2:30

























                  answered Nov 25 '18 at 16:06









                  CurneliousCurnelious

                  3,857750102




                  3,857750102






























                      draft saved

                      draft discarded




















































                      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.




                      draft saved


                      draft discarded














                      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





















































                      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







                      Popular posts from this blog

                      A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

                      Calculate evaluation metrics using cross_val_predict sklearn

                      Insert data from modal to MySQL (multiple modal on website)