Lango
Lango

Reputation: 313

Python concatenation/merging one line from one file at the time

I am willing to concatenate two file on line basis, so that every line of each file is merged consecutively in a third file.

So I have the following code and the following text files:

file1.txt
1
3
5
7

file2.txt
2
4
6

code:

from ast import literal_eval

def merge_lines():
    with open("file1.txt") as f1, open("file2.txt") as f2:
        with open("file3.txt", "r+") as tfile:
            f1_lists = (literal_eval(line) for line in f1)
            f2_lists = (literal_eval(line) for line in f2)
            for l1, l2 in zip(f1_lists, f2_lists):
                tfile.write(str(l1))
                tfile.write("\n")
                tfile.write(str(l2))
                tfile.write("\n")

combine_hands()

This works just fine as the output file looks likes:

file3.txt
1
2
3
4
5
6

My question is why the last line (number 7) of the file1.txt is not being merged?

Upvotes: 0

Views: 197

Answers (4)

lightalchemist
lightalchemist

Reputation: 10219

The last line is omitted because zip stops at the end of the shorter iterable.

What you want is probably

from itertools import zip_longest
def merge_lines():
    with open("file1.txt") as f1,\
         open("file2.txt") as f2,\
         open("file3.txt", "w") as tfile:
        for l1, l2 in zip_longest(f1, f2, fillvalue="Empty line"):
            # Or you can place a sentinel value for `fillvalue` 
            # and check it and don't write to file when you see it.                
            tfile.write(l1.strip() + "\n")
            tfile.write(l2.strip() + "\n")

or if you don't want to write out to file the empty line

for l1, l2 in zip_longest(f1, f2, fillvalue=None):
    if l1:                           
        tfile.write(l1)
    if l2:
        tfile.write(l2)

And since the default value of fillvalue is None, we can simplify it further to

for l1, l2 in zip_longest(f1, f2):
    if l1:                           
        tfile.write(l1)
    if l2:
        tfile.write(l2)

Edit

The following changes were made after reading the comment and answer from @DYZ:

  1. Fixed multi-line "with open" syntax error. Unfortunately we cannot group multi-line "with" statements using parentheses.
  2. Added second option to check for sentinel value (which I already mentioned in my original answer).

Upvotes: 3

akhil pathirippilly
akhil pathirippilly

Reputation: 1060

As others mentioned, it's because you uses normal zip() , the last line of the longest list (file) got omitted.zip will form tuples only up to the length of shorter list

Instead you can use either of the below extended zip which will pad up to longest list

    itertools.zip_longest -- in python 3.x +
    itertools.izip_longest  --in python 2.6+

Upvotes: 1

DYZ
DYZ

Reputation: 57135

With the function zip_longest, your code could be written in a very compact way:

from itertools import zip_longest
with open("file1.txt") as f1,\
     open("file2.txt") as f2,\
     open("file3.txt", "w") as tfile:
        for l1, l2 in zip_longest(f1, f2, fillvalue=''):
            if l1 != '': tfile.write(l1)
            if l2 != '': tfile.write(l2)

No explicit reading or type conversion is needed.

Upvotes: 2

Skam
Skam

Reputation: 7808

The expression zip(f1_lists, f2_lists) returns a list of tuples only as long as the shorter of the provided iterables (in your case lists). So this behavior is expected per zip documentation.

If you want to include the last line, try using itertools.ziplongest

from ast import literal_eval
from itertools import ziplongest

def merge_lines():
    with open("file1.txt") as f1, open("file2.txt") as f2:
        with open("file3.txt", "r+") as tfile:
            f1_lists = (literal_eval(line) for line in f1)
            f2_lists = (literal_eval(line) for line in f2)
            for l1, l2 in zip_longest(f1_lists, f2_lists, fillvalue='x'):
                tfile.write(str(l1))
                tfile.write("\n")
                tfile.write(str(l2))
                tfile.write("\n")

combine_hands()

Upvotes: 0

Related Questions