0

I need to be able to find differences in list that may have identical values to one another besides two added elements

example

a = ['cool task', 'b', 'another task', 'j', 'better task', 'y']
b = ['cool task', 'b', 'a task', 'j', 'another task', 'j', 'better task', 'y']

How my problem is, both 'a task' and 'another task' both are followed by a 'j'

[x for x in b if x not in a]
['a task']

Because both a and b contain 'j', it is removed from the list.

How would I make so that I end up with

['a task', 'j']
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Will B
  • 19
  • 3
  • You want to find the elements in `b` that appear more often in `b` than they do in `a`? (note that appearing once counts as appearing more often than not at all). – John Coleman Sep 25 '16 at 13:38
  • 1
    If the even elements are closely linked to the elements that follow in odd indices, you should better define a different data structure that highlights this association. – trincot Sep 25 '16 at 13:40

4 Answers4

1

For simple list - what you ask is simply searching for that next item in the list:

>>> a = ['cool task', 'b', 'another task', 'j', 'better task', 'y']
>>> b = ['cool task', 'b', 'a task', 'j', 'another task', 'j', 'better task', 'y']
>>> c = [[x, b[b.index(x) + 1]] for x in b if x not in a]
>>> c
[['a task', 'j']]

But I think you are actually aiming at using dictionary or tuples.

Tuples:

>>> a = [('cool task', 'b'), ('another task', 'j'), ('better task', 'y')]
>>> b = [('cool task', 'b'), ('a task', 'j'), ('another task', 'j'), ('better task', 'y')]
>>> c = [x for x in b if x not in a]
>>> c
[('a task', 'j')]

Dictionaries:

>>> a = {'cool task': 'b', 'another task': 'j', 'better task': 'y'}
>>> b = {'cool task': 'b', 'a task': 'j', 'another task': 'j', 'better task': 'y'}
>>> c = [(x, b[x]) for x in b if x not in a]
>>> c
[('a task', 'j')]
Uriel
  • 15,579
  • 6
  • 25
  • 46
  • Thanks for the edit, I was able to use the first answer by using c[0][then what part I wanted] – Will B Sep 25 '16 at 13:42
1

You could use the difflib.SequenceMatcher() class to enumerate added, removed and changed entries:

>>> from difflib import SequenceMatcher
>>> matcher = SequenceMatcher(a=a, b=b)
>>> added = []
>>> for tag, i1, i2, j1, j2 in matcher.get_opcodes():
...     if tag == 'insert':
...         added += b[j1:j2]
...
>>> added
['a task', 'j']

The above only focuses on added entries; if you need to know about entries that were removed or altered, then there are opcodes for those events too, see the SequenceMatcher.get_opcodes() method documentation.

However, if your entries are always paired, then just produce sets with tuples from them (using pair-wise iteration); you can then do any set operations on these:

aset = set(zip(*([iter(a)] * 2)))
bset = set(zip(*([iter(b)] * 2)))
difference = bset - aset

Demo:

>>> aset = set(zip(*([iter(a)] * 2)))
>>> bset = set(zip(*([iter(b)] * 2)))
>>> aset
{('another task', 'j'), ('cool task', 'b'), ('better task', 'y')}
>>> bset
{('a task', 'j'), ('another task', 'j'), ('cool task', 'b'), ('better task', 'y')}
>>> bset - aset
{('a task', 'j')}
Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

it works as you want:

#!/usr/bin/env python
# -*- coding: utf-8 -*-


def difference(a, b):
    a, b = (lambda x, y: (y, x) if len(set(x)) > len(set(y)) else (x, y)) (a, b)
    a_result = list(a)
    b_result = list(b)

    for z in range(len(a)):
        if a[z] in b:
            a_result.remove(a[z])
            b_result.remove(a[z])

    return a_result, b_result 
    # or
    # return a_result if len(set(a_result)) > len(set(b_result)) else b_result


def main():
    a = ['cool task', 'b', 'another task', 'j', 'better task', 'y']
    b = ['cool task', 'b', 'a task', 'j', 'another task', 'j', 'better     task', 'y']
    print(difference(a, b))


if __name__ == "__main__":
    main()
Piotrowy
  • 605
  • 8
  • 20
0

Depending on your purposes, you could possibly use Counter from the collections module:

>>> from collections import Counter
>>> a = Counter(['cool task', 'b', 'another task', 'j', 'better task', 'y'])
>>> b = Counter(['cool task', 'b', 'a task', 'j', 'another task', 'j', 'better task', 'y'])
>>> b-a
Counter({'j': 1, 'a task': 1})
>>> list((b-a).keys())
['j', 'a task']
John Coleman
  • 51,337
  • 7
  • 54
  • 119