Counting string occurrences in Python

Background: I am trying to write a simple piece of code which interfaces with gpsd to return the number of GPS satellites visible and the number which gpsd is actually using. This is at the limits of my capabilities, but I have got as far as getting a string in Python which has the information embedded.

For each satellite, there is a string pair (excuse my terminology - I don't know Python) which is either u'used': False or u'used' True. I would like the program to return two values: the total number of satellites visible (the number of u'used' strings) and the total number used (the number of u'used': True strings). Is there a nice easy way to do this?

(Were this FreePascal/Lazarus I guess it would be easy, or if I knew more JSON!).

Here the full report:

[, , , , , , , , , , , , , , , ]
--
Thanks, 
David 
Web: http://www.satsignal.eu
Reply to
David Taylor
Loading thread data ...

You should just try to google for your subject line. The second hit gave me this:

formatting link

2
Reply to
Stefan Enzinger

Great - and it seems it's a JSON encoded string so rather than doing any string processing on it why not decode it using the json module (loads method) which will turn it into a list of dicts which you can loop through something roughly like this.

import json

sats = json.loads(gps_str) total_sats = len(sats) used_sats = 0 for sat in sats: if sat['used']: used_sats = used_sats + 1

--
Steve O'Hara-Smith                          |   Directable Mirror Arrays 
C:>WIN                                      | A better way to focus the sun 
The computer obeys and wins.                |    licences available see 
You lose and Bill collects.                 |    http://www.sohara.org/
Reply to
Ahem A Rivet's Shot

Thanks, Stefan. I had searched, and tried a function such as you suggest, but unfortunately it returned 0 when searching for either "used" or "True". There were no compiler errors, but I don't know Python well enough to know where I'm going wrong.

--
Cheers, 
David 
Web: http://www.satsignal.eu
Reply to
David Taylor

On 10/04/2016 11:15, Ahem A Rivet's Shot wrote: []

Thanks, Ahem, I appreciate your help. I did try that but it seems not to work for my data at least. Here's the error message and the program:

Traceback (most recent call last): File "gpsdRead.py", line 22, in sats = json.loads (report.satellites) File "/usr/lib/python2.7/json/__init__.py", line 338, in loads return _default_decoder.decode(s) File "/usr/lib/python2.7/json/decoder.py", line 366, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) TypeError: expected string or buffer ===========================

import gps import json from collections import Counter

# Listen on port 2947 (gpsd) of localhost session = gps.gps("localhost", "2947") session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)

while True: try: report = session.next() # Wait for a 'SKY' report and display the current time # To see all report data, uncomment the line below # print report if report['class'] == 'SKY': # print report session = None if hasattr(report, 'satellites'): # print report.satellites # print report.satellites.count("used") # print report.satellites.count("True") sats = json.loads (report.satellites) total_sats = len (sats) used_sats = 0 for sat in sats: if sat['used']: used_sats = used_sats + 1 print total_sats print used_sats session = None quit() except KeyError: pass except KeyboardInterrupt: quit() except StopIteration: session = None print "GPSD has terminated"

--
Cheers, 
David 
Web: http://www.satsignal.eu
Reply to
David Taylor

Show us the code you wrote, then we *might* have some chance of suggesting what's wrong.

(... and Python isn't a compiler)

--
Chris Green
Reply to
cl

On Sun, 10 Apr 2016 15:17:37 +0100, David Taylor declaimed the following:

From your earlier post:

How did you produce that "report". I'm not up on JSON myself, but those structures don't seem valid. With them in place I get

ValueError: No JSON object could be decoded

Removing them got me to

ValueError: Expecting property name: line 2 column 3 (char 3)

After much trial and error I managed to get

report = """ [ {"ss": 24, "el": 10, "PRN": 67, "az": 130, "used":"False"}, {"ss": 30, "el": 63, "PRN": 68, "az": 130, "used":"False"}, {"ss": 14, "el": 59, "PRN": 69, "az": 309, "used":"False"}, {"ss": 12, "el": 73, "PRN": 78, "az": 118, "used": "False"}, {"ss": 26, "el": 39, "PRN": 79, "az": 190, "used":"False"}, {"ss": 17, "el": 18, "PRN": 85, "az": 315, "used":"False"}, {"ss": 31, "el": 26, "PRN": 136, "az": 170, "used":"True"}, {"ss": 30, "el": 23, "PRN": 28, "az": 137, "used": "True"}, {"ss": 38, "el": 66, "PRN": 30, "az": 92, "used":"True"}, {"ss": 31, "el": 40, "PRN": 20, "az": 297, "used":"True"}, {"ss": 27, "el": 15, "PRN": 21, "az": 327, "used":"True"}, {"ss": 11, "el": 8, "PRN": 27, "az": 23, "used":"False"}, {"ss": 32, "el": 66, "PRN": 5, "az": 212, "used": "True"}, {"ss": 27, "el": 40, "PRN": 7, "az": 61, "used": "True"}, {"ss": 17, "el": 4, "PRN": 9, "az": 96, "used":"False"}, {"ss": 38, "el": 54, "PRN": 13, "az": 269, "used":"True"} ] """ to feed to the loader. The order has changed as I was cut&pasting from one record up to the full set. Note that I had to:

1) remove the 2) remove the u' leaving just the ' (actually, I also ended up changing all ' to ") 3) True and False had to be quoted; without the quotes I got errors.

How you massage your input data to fit is another matter...

-=-=-=-=- import json

report = """ [ {"ss": 24, "el": 10, "PRN": 67, "az": 130, "used":"False"}, {"ss": 30, "el": 63, "PRN": 68, "az": 130, "used":"False"}, {"ss": 14, "el": 59, "PRN": 69, "az": 309, "used":"False"}, {"ss": 12, "el": 73, "PRN": 78, "az": 118, "used": "False"}, {"ss": 26, "el": 39, "PRN": 79, "az": 190, "used":"False"}, {"ss": 17, "el": 18, "PRN": 85, "az": 315, "used":"False"}, {"ss": 31, "el": 26, "PRN": 136, "az": 170, "used":"True"}, {"ss": 30, "el": 23, "PRN": 28, "az": 137, "used": "True"}, {"ss": 38, "el": 66, "PRN": 30, "az": 92, "used":"True"}, {"ss": 31, "el": 40, "PRN": 20, "az": 297, "used":"True"}, {"ss": 27, "el": 15, "PRN": 21, "az": 327, "used":"True"}, {"ss": 11, "el": 8, "PRN": 27, "az": 23, "used":"False"}, {"ss": 32, "el": 66, "PRN": 5, "az": 212, "used": "True"}, {"ss": 27, "el": 40, "PRN": 7, "az": 61, "used": "True"}, {"ss": 17, "el": 4, "PRN": 9, "az": 96, "used":"False"}, {"ss": 38, "el": 54, "PRN": 13, "az": 269, "used":"True"} ] """

result = json.loads(report) print "Reported PRNs: ", len(result) print "Visible PRNs: ", len([rec for rec in result if rec[u"used"] == u"True"])

-=-=-=-=-=-

Reported PRNs: 16 Visible PRNs: 8

--
	Wulfraed                 Dennis Lee Bieber         AF6VN 
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/
Reply to
Dennis Lee Bieber

There are newsgroups for python too, which should be used in preference unless your problem is specific to the Raspberry Pi, which in this case it isn't.

---druck

Reply to
druck

You're right, of course, about the newsgroups, although in this case the issues /may/ be RPi-specific since it has not got the up-to-date versions of gpsd. I'm more tending towards writing my own program in Pascal (Lazarus) as the delay in getting the required message (SKY) is annoying me!

--
Cheers, 
David 
Web: http://www.satsignal.eu
Reply to
David Taylor

Ah I see it's already structured and what you posted was the result of python turning it into a string to print it - then I was trying to get you to turn it back into what you started with :)

Life is simpler for you. Ignore this bit:

In here use report.satellites where I have sats.

Or you can use the more compact way of counting suggested by Dennis - I wouldn't because it allocates an array that isn't used for anything but counting it's length.

One more thing this:

Would be nicer as:

if 'satellites' in report:

--
Steve O'Hara-Smith                          |   Directable Mirror Arrays 
C:>WIN                                      | A better way to focus the sun 
The computer obeys and wins.                |    licences available see 
You lose and Bill collects.                 |    http://www.sohara.org/
Reply to
Ahem A Rivet's Shot

Yes, comp.lang.python is a very friendly and helpful newsgroup.

--
Chris Green
Reply to
cl

Thanks for that, Steve. It's now written up here:

formatting link

and your help is acknowledged. If anyone else feels they should be acknowledged please let me know.

--
Cheers, 
David 
Web: http://www.satsignal.eu
Reply to
David Taylor

Thanks for everyone's help with this. Whilst I did get a working solution with Python, I found a much quick way was to write a small piece of C. For those interested, please see:

formatting link

--
Cheers, 
David 
Web: http://www.satsignal.eu
Reply to
David Taylor

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.