patternpythonMinor
Python code for detecting a single item moved in a list
Viewed 0 times
itemmovedsingleforpythoncodelistdetecting
Problem
I need to write a function that takes an original list of unique values and a resulting list:
and detect that only a single element was moved then report exactly what was moved where. If the resulting list is not the result of moving exactly one item from source to destination, this code should fail.
Here are some examples:
location 3 was moved to location 1
Failure cases (not exactly one move could be detected) include:
(before/after have different items)
(before has duplicate values)
(before/after not the same size)
My basic approach is to iterate both lists simultaneously until there's a difference. If the destination list has a different item, then we see if the next item matches the source lists current item. This indicates that something has been inserted at this point. We then move forward the destination list and proceed. We notice removals in a similar process. If the we've decided its not an insertion, that is two items are not equal but the source does NOT continue in the destination list, then we treat it as a removal.
In the case of an insertion, we only move the destination list forward. We expect the rest of the dest list/src list to match up until we detect a removal. In the case of detecting a removal, we move forward the source list. If both elements are equal, we move them both forward.
For example:
`original: result:
1-
[0,1,2,3]
[0,3,1,2]
and detect that only a single element was moved then report exactly what was moved where. If the resulting list is not the result of moving exactly one item from source to destination, this code should fail.
Here are some examples:
[0,1,2,3]
[0,3,1,2]
location 3 was moved to location 1
Failure cases (not exactly one move could be detected) include:
[4,1,2,3]
[1,3,1,2]
(before/after have different items)
[1,1,2,3]
[1,3,1,2]
(before has duplicate values)
[4,5,1,2,3]
[1,3,1,2]
(before/after not the same size)
My basic approach is to iterate both lists simultaneously until there's a difference. If the destination list has a different item, then we see if the next item matches the source lists current item. This indicates that something has been inserted at this point. We then move forward the destination list and proceed. We notice removals in a similar process. If the we've decided its not an insertion, that is two items are not equal but the source does NOT continue in the destination list, then we treat it as a removal.
In the case of an insertion, we only move the destination list forward. We expect the rest of the dest list/src list to match up until we detect a removal. In the case of detecting a removal, we move forward the source list. If both elements are equal, we move them both forward.
For example:
original: result:
1----------4 // not equal, peek ahead and compare 1==1, this is just an insertion
2--- \-----1 // 1 == 1 same
3-- \------2 // 2 == 2 same
4- \-------3 // 3 == 3 same
\-------- // result exhausted, removal
original: result:
1----\-----4 // not equal, peek ahead and compare 1==1, this is an insertion, move just result ahead 1
2--\ \----1 // 1 == 1 same
3-\ \------2 // 2 == 2 same
4\ \-------3 // 3 == 3 same
\-------- // result exhausted, removal
`original: result:
1-
Solution
This seems a shorter solution:
PS: this works also if the items are non unique.
def findMove(original,result):
if len(original) != len(result):
return # different length
diff = [x for x,(c,d) in enumerate(zip(original,result)) if c!=d]
if not diff:
return # equal strings
i,j = diff[0],diff[-1]
if original[i+1:j+1] == result[i:j] and original[i] == result[j]:
return (i,j)
if original[i:j] == result[i+1:j+1] and original[j] == result[i]:
return (j,i)PS: this works also if the items are non unique.
Code Snippets
def findMove(original,result):
if len(original) != len(result):
return # different length
diff = [x for x,(c,d) in enumerate(zip(original,result)) if c!=d]
if not diff:
return # equal strings
i,j = diff[0],diff[-1]
if original[i+1:j+1] == result[i:j] and original[i] == result[j]:
return (i,j)
if original[i:j] == result[i+1:j+1] and original[j] == result[i]:
return (j,i)Context
StackExchange Code Review Q#61282, answer score: 4
Revisions (0)
No revisions yet.