简体   繁体   中英

Compare two sets of strings and then return whole strings that are different in Python 3.4

I'm writing a small API listening program, and I'm trying to figure out when something new has been published. I've figured out most of it, but I'm having a problem on the last step -- where I want to print out something new. I can compare the two lists of items as sets and get the set of letters that's in the right answer, but I can't seem to get the actual strings to print.

Here's the code I wrote to compare the two lists (both new_revised_stuff and old_revised_stuff are lists of strings, like "Bob likes to eat breakfast at http://bobsburgers.com" with a few dozen items per list).

new_stuff = set(new_revised_stuff) - set(old_revised_stuff).intersection(new_revised_stuff)

Which returns:

set('b','o','l'...)

I can get rid of the 'set' notation by writing:

list(new_stuff)

But that doesn't really help. I'd really like it to print out "Bob likes..." if that's a new line.

I've also tried:

new_stuff = []
for a in new_revised_stuff:
    for b in old_revised_stuff:
        if a != b:
            ''.join(a)
            new_stuff.append(a)

Which results in an actual stack overflow, so it's obviously bad code.

If you want to join any iterable of single characters into a string, you do that with ''.join(new_stuff) . For example:

>>> new_stuff = ['b','o','l']
>>> ''.join(new_stuff)
'bol'

However, there are two problems here, that are inherent in your design:

  • Sets only hold unique elements. So, if your string diffs are "Hello, Bob" , there's only going to be one o and one l in the set of diffs.
  • Sets are arbitrarily ordered. So, if your string diffs are "Bob likes" , converting that into a set and then back to a string will get you something like 'k iboeBls' .

If either of those is a problem (and I suspect they are), you need to rethink your algorithm. You can solve the second one by using an OrderedSet (there's a recipe for that in the collections docs), but the first one is going to be more of a problem.

So, how could you do this?

Well, you don't really need new_revised_stuff to be a set; if you iterate over the characters and keep only the ones that aren't in old_revised_stuff , as long as old_revised_stuff is a set, that's just as efficient as intersecting two sets.

But making old_revised_stuff a set will also eliminate any duplicates there, which I don't think you want. What you really want is a "multiset". In Python, the best way to represent that is usually a Counter .

So, I think what you want (maybe) is something like this:

old_string = ' to eat breakfast at http://bobsburgers.com'
new_string = 'Bob likes to eat breakfast at http://bobsburgers.com'
old_chars = collections.Counter(old_string)
new_chars = []
for ch in new_string:
    if old_chars[ch]:
        old_chars[ch] -= 1
    else:
        new_chars.append(ch)
new_string = ''.join(new_chars)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM