Python Forum
splitting lines, need to add element of same kind - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: splitting lines, need to add element of same kind (/thread-32595.html)



splitting lines, need to add element of same kind - tester_V - Feb-20-2021

Hi,
I need to 'sum' all elements by their kind.
All dogs, cats, and fishes.
I Cannot wrap around my mind around this small task.
Here is a kind of file as an example:

line01,P,2,dog
line02,P,1,dog
line33,P,7,dog
line03,P,3,cat
line04,P,5,cat
line11,P,8,fish
line12,P,3,dog
line16,P,2,dog
line04,P,2,cat
line11,P,12,fish

I need to print out a number of Dogs, Cats, and fishes and replace the first line with a time stamp.
19/02/2021,P,15 dog
19/02/2021,P,10,cat
19/02/2021,P,20,fish
I scanned the file and made a list of the animals --- 'list'.
And I thought I would use the list to filter 'animals' by its kind and 'sum' them, for some reason it does not work.
Code:
from datetime import datetime

now = datetime.now()
date_time = now.strftime("%m/%d/%Y")
to_app ='C:/02/All_an.txt'

list = ['dog','cat','fish']

with open (to_app, 'r+') as app : 
    for ln_in_file in app :
        ln_in_file=ln_in_file.strip()

        for ech_element in list :
            Sum = 0
            if ech_element in ln_in_file :
                spel =ln_in_file.split(",")
                spel[2]=int(spel[2])
                print ("======================== ",spel[2])
                
                Sum=(spel[2]+spel[2])
                break
        print (Sum)  
I'm opening my file with 'r+' for some reason the file is not readable if I open it with 'append'
Thank you.


RE: splitting lines, need to add element of same kind - deanhystad - Feb-20-2021

A dictionary makes this easy.
source = [
    '5, cat',
    '3, dog',
    '1, cat',
    '1, fish',
    '2, dog',
    '3, bird']

animals = {}

for line in source:
    count, animal = line.split(',')
    animals[animal] = animals.get(animal, 0) + int(count)

print(animals)
Output:
{' cat': 6, ' dog': 5, ' fish': 1, ' bird': 3}
If you only want to count certain animals:
source = [
    '5, cat',
    '3, dog',
    '1, cat',
    '1, fish',
    '2, dog',
    '3, bird']

animals = {'cat':0, 'dog':0}

for line in source:
    count, animal = line.split(',')
    if animal in animals:
        animals[animal] += int(count)

print(animals)
Output:
{'cat': 0, 'dog': 0}



RE: splitting lines, need to add element of same kind - bowlofred - Feb-20-2021

On line 20 you change Sum to be (spel[2] + spel[2]), so it doesn't depend on any previous value. It's not summing up anything. Also, you're not keeping a separate value for each animal.


RE: splitting lines, need to add element of same kind - deanhystad - Feb-20-2021

Using a list you would need two lists, animals and animal counts.
to_app ='C:/02/All_an.txt'
 
animals = ['dog','cat','fish']  # Never use list as a variable name
counts = [0, 0, 0]
 
with open (to_app, 'r+') as app: 
    for line in app :
        line = line.strip()

        for index, animal in enumerate(animals):
            if animal in line:
                parts = line.split(",")
                count[index] += int(parts[2])
                break

for animal, count in zip(animals, counts):
    print(animal, count)
This code is hideous because there is no association between the count and the animal other than the position in the list. Since Python provides a datatype who's entire reason for existing is to provide a tight coupling, may as well use that.


RE: splitting lines, need to add element of same kind - Serafim - Feb-20-2021

Without any assumption about the number of different animals in the file maybe something like this.
from datetime import datetime
 
now = datetime.now()
date_time = now.strftime("%m/%d/%Y")
to_app ='C:/02/All_an.txt'
 
animals = dict()

with open (to_app, 'r+') as app:
    for ln_in_file in app :
        ln_in_file=ln_in_file.strip()

        line, P, num, animal = ln_in_file.split(',')
        if animal in animals:
            animals[animal]['count'] += int(num)
        else:
            animals[animal] = {'count': int(num), 'P': P, 'date': date_time}

for animal in animals:    
    print(f"{animals[animal]['date']},{animals[animal]['count']},{animals[animal]['P']},{animal}")
As I don't know anything about the function of 'P' and 'lineNN', I omitted the 'lineNN' and replaced it with the date, but kept the rest. If this is not necessary, the code can be much simplified:
from datetime import datetime
 
now = datetime.now()
date_time = now.strftime("%m/%d/%Y")
to_app ='C:/02/All_an.txt'
 
animals = dict()

with open (to_app, 'r+') as app:
    for ln_in_file in app :
        ln_in_file=ln_in_file.strip()

        line, P, num, animal = ln_in_file.split(',')
        if animal in animals:
            animals[animal] += int(num)
        else:
            animals[animal] = int(num)

for animal, count in animals.items():
    print(f"{date_time},{count},P,{animal}")



RE: splitting lines, need to add element of same kind - perfringo - Feb-20-2021

If anything is to be counted my first thought is to go for Counter which happens to be Python's data type for counting.

Assuming that file data.csv containing sample data one can achieve desired output (in descending order):

from collections import Counter
from datetime import datetime as dt


with open('data.csv', 'r') as f:
    count = Counter()
    for line in f:
        _, marker, qty, item = line.strip().split(',')
        count.update({item: int(qty)})

timestamp = dt.today().date().strftime("%d/%m/%Y")

for item, qty in count.most_common():              # for ascending order: count.most_common()[::-1]
    print(f'{timestamp},{marker},{qty},{item}')     

20/02/2021,P,20,fish
20/02/2021,P,15,dog
20/02/2021,P,10,cat



RE: splitting lines, need to add element of same kind - tester_V - Feb-20-2021

I think you need to know that many of us here in this forum think guys are great!

Just to clarify, the list of (animals) could hold any number of animals.
First, I'm scanning the file just to create the list,
I thought it will help me to get the sum of each "animal" from the list.
The file is not .CSV.

I'm going to try all of your suggestions later tonight.
Thank you again!