Adding rows to CSV sorted by ID in Python without reading whole file into memory











up vote
2
down vote

favorite












I have a CSV file where the first column is an ID like so:



5,a
4,b
2,c
1,d


The rows must always be sorted from the biggest to smallest ID. I have a list of rows that I want to add, without reading the whole original CSV in memory, so I can't just append the rows and sort after. Here is the code I came up with:



import csv


def main():
rows_to_add = [[7, "NEW1"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
reader = csv.reader(in_file)
writer = csv.writer(out_file)

for new_row in rows_to_add:
for source_row in reader:
if new_row[0] >= int(source_row[0]):
writer.writerow(new_row)
writer.writerow(source_row)
break

writer.writerow(source_row)
else:
# If source reader already reached end of file
writer.writerow(new_row)

for remaining_line in in_file:
out_file.write(remaining_line)

with open("out.csv", "r") as out_file:
print(out_file.read())


if __name__ == "__main__":
main()


Result:



7,NEW1
5,a
6,NEW2
4,b
3,NEW3
2,c
1,d
-2,NEW4


This doesn't work correctly if there are two consecutive IDs, 6,NEW2 should be just after 7,NEW1 and I can't figure out the right way to do it.










share|improve this question




























    up vote
    2
    down vote

    favorite












    I have a CSV file where the first column is an ID like so:



    5,a
    4,b
    2,c
    1,d


    The rows must always be sorted from the biggest to smallest ID. I have a list of rows that I want to add, without reading the whole original CSV in memory, so I can't just append the rows and sort after. Here is the code I came up with:



    import csv


    def main():
    rows_to_add = [[7, "NEW1"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

    with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
    reader = csv.reader(in_file)
    writer = csv.writer(out_file)

    for new_row in rows_to_add:
    for source_row in reader:
    if new_row[0] >= int(source_row[0]):
    writer.writerow(new_row)
    writer.writerow(source_row)
    break

    writer.writerow(source_row)
    else:
    # If source reader already reached end of file
    writer.writerow(new_row)

    for remaining_line in in_file:
    out_file.write(remaining_line)

    with open("out.csv", "r") as out_file:
    print(out_file.read())


    if __name__ == "__main__":
    main()


    Result:



    7,NEW1
    5,a
    6,NEW2
    4,b
    3,NEW3
    2,c
    1,d
    -2,NEW4


    This doesn't work correctly if there are two consecutive IDs, 6,NEW2 should be just after 7,NEW1 and I can't figure out the right way to do it.










    share|improve this question


























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I have a CSV file where the first column is an ID like so:



      5,a
      4,b
      2,c
      1,d


      The rows must always be sorted from the biggest to smallest ID. I have a list of rows that I want to add, without reading the whole original CSV in memory, so I can't just append the rows and sort after. Here is the code I came up with:



      import csv


      def main():
      rows_to_add = [[7, "NEW1"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

      with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
      reader = csv.reader(in_file)
      writer = csv.writer(out_file)

      for new_row in rows_to_add:
      for source_row in reader:
      if new_row[0] >= int(source_row[0]):
      writer.writerow(new_row)
      writer.writerow(source_row)
      break

      writer.writerow(source_row)
      else:
      # If source reader already reached end of file
      writer.writerow(new_row)

      for remaining_line in in_file:
      out_file.write(remaining_line)

      with open("out.csv", "r") as out_file:
      print(out_file.read())


      if __name__ == "__main__":
      main()


      Result:



      7,NEW1
      5,a
      6,NEW2
      4,b
      3,NEW3
      2,c
      1,d
      -2,NEW4


      This doesn't work correctly if there are two consecutive IDs, 6,NEW2 should be just after 7,NEW1 and I can't figure out the right way to do it.










      share|improve this question















      I have a CSV file where the first column is an ID like so:



      5,a
      4,b
      2,c
      1,d


      The rows must always be sorted from the biggest to smallest ID. I have a list of rows that I want to add, without reading the whole original CSV in memory, so I can't just append the rows and sort after. Here is the code I came up with:



      import csv


      def main():
      rows_to_add = [[7, "NEW1"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

      with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
      reader = csv.reader(in_file)
      writer = csv.writer(out_file)

      for new_row in rows_to_add:
      for source_row in reader:
      if new_row[0] >= int(source_row[0]):
      writer.writerow(new_row)
      writer.writerow(source_row)
      break

      writer.writerow(source_row)
      else:
      # If source reader already reached end of file
      writer.writerow(new_row)

      for remaining_line in in_file:
      out_file.write(remaining_line)

      with open("out.csv", "r") as out_file:
      print(out_file.read())


      if __name__ == "__main__":
      main()


      Result:



      7,NEW1
      5,a
      6,NEW2
      4,b
      3,NEW3
      2,c
      1,d
      -2,NEW4


      This doesn't work correctly if there are two consecutive IDs, 6,NEW2 should be just after 7,NEW1 and I can't figure out the right way to do it.







      python csv






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 15 at 1:22

























      asked Nov 15 at 0:36









      sena

      134




      134
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote



          accepted










          You have to use a running pointer for at least one of the lists. In this case, as you can't read the entire CSV, the running pointer can be used for the other list



          Following code should work



          import csv


          def main():
          rows_to_add = [[7, "NEW1"], [6, "NEW2"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

          with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
          reader = csv.reader(in_file)
          writer = csv.writer(out_file)
          idx = 0

          # For each line in file
          for source_row in reader:
          # Print all rows from rows_to_add that are larger
          while rows_to_add[idx][0] > int(source_row[0]):
          writer.writerow(rows_to_add[idx])
          idx += 1

          # Before printing current line from file
          writer.writerow(source_row)

          # Print remaining rows in rows_to_add
          for row in rows_to_add[idx:]:
          writer.writerow(row)


          with open("out.csv", "r") as out_file:
          print(out_file.read())


          if __name__ == "__main__":
          main()


          sample output for your in.csv



          7,NEW1
          6,NEW2
          6,NEW2
          5,a
          4,b
          3,NEW3
          2,c
          1,d
          -2,NEW4





          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',
            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%2f53310840%2fadding-rows-to-csv-sorted-by-id-in-python-without-reading-whole-file-into-memory%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote



            accepted










            You have to use a running pointer for at least one of the lists. In this case, as you can't read the entire CSV, the running pointer can be used for the other list



            Following code should work



            import csv


            def main():
            rows_to_add = [[7, "NEW1"], [6, "NEW2"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

            with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
            reader = csv.reader(in_file)
            writer = csv.writer(out_file)
            idx = 0

            # For each line in file
            for source_row in reader:
            # Print all rows from rows_to_add that are larger
            while rows_to_add[idx][0] > int(source_row[0]):
            writer.writerow(rows_to_add[idx])
            idx += 1

            # Before printing current line from file
            writer.writerow(source_row)

            # Print remaining rows in rows_to_add
            for row in rows_to_add[idx:]:
            writer.writerow(row)


            with open("out.csv", "r") as out_file:
            print(out_file.read())


            if __name__ == "__main__":
            main()


            sample output for your in.csv



            7,NEW1
            6,NEW2
            6,NEW2
            5,a
            4,b
            3,NEW3
            2,c
            1,d
            -2,NEW4





            share|improve this answer

























              up vote
              0
              down vote



              accepted










              You have to use a running pointer for at least one of the lists. In this case, as you can't read the entire CSV, the running pointer can be used for the other list



              Following code should work



              import csv


              def main():
              rows_to_add = [[7, "NEW1"], [6, "NEW2"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

              with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
              reader = csv.reader(in_file)
              writer = csv.writer(out_file)
              idx = 0

              # For each line in file
              for source_row in reader:
              # Print all rows from rows_to_add that are larger
              while rows_to_add[idx][0] > int(source_row[0]):
              writer.writerow(rows_to_add[idx])
              idx += 1

              # Before printing current line from file
              writer.writerow(source_row)

              # Print remaining rows in rows_to_add
              for row in rows_to_add[idx:]:
              writer.writerow(row)


              with open("out.csv", "r") as out_file:
              print(out_file.read())


              if __name__ == "__main__":
              main()


              sample output for your in.csv



              7,NEW1
              6,NEW2
              6,NEW2
              5,a
              4,b
              3,NEW3
              2,c
              1,d
              -2,NEW4





              share|improve this answer























                up vote
                0
                down vote



                accepted







                up vote
                0
                down vote



                accepted






                You have to use a running pointer for at least one of the lists. In this case, as you can't read the entire CSV, the running pointer can be used for the other list



                Following code should work



                import csv


                def main():
                rows_to_add = [[7, "NEW1"], [6, "NEW2"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

                with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
                reader = csv.reader(in_file)
                writer = csv.writer(out_file)
                idx = 0

                # For each line in file
                for source_row in reader:
                # Print all rows from rows_to_add that are larger
                while rows_to_add[idx][0] > int(source_row[0]):
                writer.writerow(rows_to_add[idx])
                idx += 1

                # Before printing current line from file
                writer.writerow(source_row)

                # Print remaining rows in rows_to_add
                for row in rows_to_add[idx:]:
                writer.writerow(row)


                with open("out.csv", "r") as out_file:
                print(out_file.read())


                if __name__ == "__main__":
                main()


                sample output for your in.csv



                7,NEW1
                6,NEW2
                6,NEW2
                5,a
                4,b
                3,NEW3
                2,c
                1,d
                -2,NEW4





                share|improve this answer












                You have to use a running pointer for at least one of the lists. In this case, as you can't read the entire CSV, the running pointer can be used for the other list



                Following code should work



                import csv


                def main():
                rows_to_add = [[7, "NEW1"], [6, "NEW2"], [6, "NEW2"], [3, "NEW3"], [-2, "NEW4"]]

                with open("in.csv", "r") as in_file, open("out.csv", "w") as out_file:
                reader = csv.reader(in_file)
                writer = csv.writer(out_file)
                idx = 0

                # For each line in file
                for source_row in reader:
                # Print all rows from rows_to_add that are larger
                while rows_to_add[idx][0] > int(source_row[0]):
                writer.writerow(rows_to_add[idx])
                idx += 1

                # Before printing current line from file
                writer.writerow(source_row)

                # Print remaining rows in rows_to_add
                for row in rows_to_add[idx:]:
                writer.writerow(row)


                with open("out.csv", "r") as out_file:
                print(out_file.read())


                if __name__ == "__main__":
                main()


                sample output for your in.csv



                7,NEW1
                6,NEW2
                6,NEW2
                5,a
                4,b
                3,NEW3
                2,c
                1,d
                -2,NEW4






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 15 at 1:58









                Krishna

                5941315




                5941315






























                    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.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • 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%2f53310840%2fadding-rows-to-csv-sorted-by-id-in-python-without-reading-whole-file-into-memory%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

                    How to change which sound is reproduced for terminal bell?

                    Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

                    Can I use Tabulator js library in my java Spring + Thymeleaf project?