'str' object has no attribute 'remove' - list

I want to remove 362968 from below list-
list=[362976,362974,362971,362968,362969]
code-
list.remove(362968)
I am getting error: 'str' object has no attribute 'remove'
Actual code -
def matchmaker():
exportersfree = exporters[:]
engaged = {}
exprefers2 = copy.deepcopy(exprefers)
imprefers2 = copy.deepcopy(imprefers)
while exportersfree:
exporter = exportersfree.pop(0)
exporterslist = exprefers2[exporter]
importer = exporterslist.pop(0)
match = engaged.get(importer)
if not match:
# impo's free
engaged[importer] = exporter #both parties are added to the engaged list
importerslist = imprefers2[importer]
for z in range (importerslist.index(exporter)-1):
importerslist.index(exporter)
exprefers2[importerslist[z]].remove(importer)
del importerslist[0:(importerslist.index(exporter)-1)]
else
engaged[importer] = exporter
if exprefers2[match]:
# Ex has more importers to try
exportersfree.append(match)
return engaged

Without additional code to really debug, exprefers2is clearly a dict of strings; however, if you really want to delete it. You can cast the string to a list, or eval the value to convert it into a list, then use list.remove
import ast
list = [1, 2, 3, 4, 5, 6, 7]
list.remove(5)
print list
#[1, 2, 3, 4, 6, 7]
#Data Structure you most likely have
import_list = [1, 2]
exprefers2 = {1: "abc", 2: "xyz"}
print exprefers2[import_list[1]]
#xyz
#Or need to eval the string of a list
import_list = [1, 2]
exprefers2 = {1: u'[ "A","B","C" , " D"]', 2: u'[ "z","x","y" , " y"]'}
exprefers2[import_list[1]] = ast.literal_eval(exprefers2[import_list[1]])
exprefers2[import_list[1]].remove("y")
print exprefers2[import_list[1]]
#['z', 'x', ' y']

Try it in this way then, name your list "a".
a = [362976,362974,362971,362968,362969]
a.remove(362968)
print a

I think you need to check if the X has been changed.
x = [1, 40, 33, 20]
x.remove(33)
print (x)

Related

Mock file read in binary mode in Python 2.7

I'm trying to unit test the file reading in binary in Python 2.7. but failing miserably.
test_my_module:
def test_read_binary(self):
d = {
"offset": [1, 4, 5, 7],
"bytes" : [3, 1, 2, 3]
}
spec = pd.DataFrame(d)
input_file = 'input.bin'
fake_file = StringIO.StringIO('foo\nbar\n')
with mock.patch('my_module.open', return_value=fake_file, create=True):
full_spec = self._tt.read_binary(spec, input_file)
print full_spec
my_module:
def read_binary(self, spec, input_file):
with open(input_file, 'rb') as infile:
def read_data(row):
print 'ROW:', row
infile.seek(row['offset'], 0)
value = infile.read(row['bytes'])
print value
return value
spec['raw'] = spec.apply(read_data, axis=1)
return spec
This produces the following exception:
AttributeError: StringIO instance has no attribute 'exit'
Any suggestions how to go about it?
For reference, I solved the problem using the following function:
def mock_open(self, mock_o=None, data=None):
file_spec = file
if mock_o is None:
mock_o = mock.MagicMock(spec=file_spec)
handle = mock.MagicMock(spec=file_spec)
handle.write.return_value = None
if data is None:
handle.__enter__.return_value = handle
else:
handle.__enter__.return_value = data
mock_o.return_value = handle
return mock_o
def test_read_binary(self):
data = b'\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64' # helloworld
d = {
'offset': [0, 4, 5, 7],
'bytes': [3, 1, 2, 3]
}
spec = pd.DataFrame(d)
input_file = 'input.bin'
expected_list = [b'\x68\x65\x6c', b'\x6f', b'\x77\x6f', b'\x72\x6c\x64']
m = self.mock_open(data=StringIO.StringIO(data))
with mock.patch('__builtin__.open', m, create=True):
full_spec = self._tt.read_binary(spec, input_file)
self.assertListEqual(expected_list, full_spec['raw'].tolist())

How do i check for duplicate values present in a Dictionary?

I want to map a function that takes a dictionary as the input and returns a list of the keys.
The keys in the list must be of only the unique values present in the dictionary.
So, this is what I have done.
bDict={}
for key,value in aDict.items():
if bDict.has_key(value) == False:
bDict[value]=key
else:
bDict.pop(value,None)
This is the output :
>>> aDict.keys()
Out[4]: [1, 3, 6, 7, 8, 10]
>>> aDict.values()
Out[5]: [1, 2, 0, 0, 4, 0]
>>> bDict.keys()
Out[6]: [0, 1, 2, 4]
>>> bDict.values()
Out[7]: [10, 1, 3, 8]
But, the expected output should be for bDict.values() : [*1,3,8*]
This may help.
CODE
aDict = { 1:1, 3:2, 6:0, 7:0, 8:4, 10:0, 11:0}
bDict = {}
for i,j in aDict.items():
if j not in bDict:
bDict[j] = [i]
else:
bDict[j].append(i)
print map(lambda x: x[0],filter(lambda x: len(x) == 1,bDict.values()))
OUTPUT
[1, 3, 8]
So it appears you're creating a new dictionary with the keys and values inverted, keeping pairs where the value is unique. You can figure out which of the items are unique first then build a dictionary off of that.
def distinct_values(d):
from collections import Counter
counts = Counter(d.itervalues())
return { v: k for k, v in d.iteritems() if counts[v] == 1 }
This yields the following result:
>>> distinct_values({ 1:1, 3:2, 6:0, 7:0, 8:4, 10:0 })
{1: 1, 2: 3, 4: 8}
Here is a solution (with two versions of the aDict to test a rand case which failed in another solution):
#aDict = { 1:1, 3:2, 6:0, 7:0, 8:4, 10:0}
aDict = { 1:1, 3:2, 6:0, 7:0, 8:4, 10:0, 11:2}
seenValues = {}
uniqueKeys = set()
for aKey, aValue in aDict.items():
if aValue not in seenValues:
# Store the key of the value, and assume it is unique
seenValues[aValue] = aKey
uniqueKeys.add(aKey)
elif seenValues[aValue] in uniqueKeys:
# The value has been seen before, and the assumption of
# it being unique was wrong, so remove it
uniqueKeys.remove(seenValues[aValue])
print "Remove non-unique key/value pair: {%d, %d}" % (aKey, aValue)
else:
print "Non-unique key/value pair: {%d, %d}" % (aKey, aValue)
print "Unique keys: ", sorted(uniqueKeys)
And this produces the output:
Remove non-unique key/value pair: {7, 0}
Non-unique key/value pair: {10, 0}
Remove non-unique key/value pair: {11, 2}
Unique keys: [1, 8]
Or with original version of aDict:
Remove non-unique key/value pair: {7, 0}
Non-unique key/value pair: {10, 0}
Unique keys: [1, 3, 8]
As a python 2.7 one-liner,
[k for k,v in aDict.iteritems() if aDict.values().count(v) == 1]
Note that the above
Calls aDict.values() many times, once for each entry in the dictionary, and
Calls aDict.values().count(v) multiple times for each replicated value.
This is not a problem if the dictionary is small. If the dictionary isn't small, the creation and destruction of those duplicative lists and the duplicative calls to count() may be costly. It may help to cache the value of adict.values(), and it may also help to create a dictionary that maps the values in the dictionary to the number of occurrences as a dictionary entry value.

How to parse given types of string to list?

The user input string follows the pattern:
{ 1, 2, 4, 6, 3 }
{ 2, 5, 8, 0, 3, 45, 5 }
How to convert any one of the given user input to list of integers.
Maybe split can be used as in A.split(', ') but then we get,
A = ['{ 1', '2', '4', '6', '3 }']
but the answer, we want should be,
A = [1, 2, 4, 6, 3]
replace {} to [] and use json module to parse:
>>> import json
>>> s = "{ 1, 2, 4, 6, 3 }"
>>> json.loads(s.replace("{","[").replace("}","]"))
[1, 2, 4, 6, 3]
The easy way would be to strip the parentheses, split on commas and cast the types.
A = [int(x) for x in A.lstrip(' (').rstrip(' )').split(', ')]
The proper way to do this is the same way a compiler would do it: tokenize the input before parsing, using a library like PLY.
(Also, you should make an effort to do your own homework and learn to write proper English.)
You can leverage try and except to accomplish this. Basically you try to convert each character of your string to int, if successful then you append it to a list if Python raises an error -because cannot convert to int- then nothing will be appended. Maybe this is not the shortest code but it is definitely very readable.
s = '{ 1, 2, 4, 6, 3 }'
result = []
for item in s:
try:
result.append(int(item))
except:
pass
print(result)
>>>[1, 2, 4, 6, 3]

slice a dictionary on elements contained within item arrays

Say I have a dict of country -> [cities] (potentially an ordered dict):
{'UK': ['Bristol', 'Manchester' 'London', 'Glasgow'],
'France': ['Paris', 'Calais', 'Nice', 'Cannes'],
'Germany': ['Munich', 'Berlin', 'Cologne']
}
The number of keys (countries) is variable: and the number of elements cities in the array, also variable. The resultset comes from a 'search' on city name so, for example, a search on "San%" could potentially meet with 50k results (on a worldwide search)
The data is to be used to populate a select2 widget --- and I'd like to use its paging functionality...
Is there a smart way to slice this such that [3:8] would yield:
{'UK': ['Glasgow'],
'France': ['Paris', 'Calais', 'Nice', 'Cannes'],
'Germany': ['Munich']
}
(apologies for the way this question was posed earlier -- I wasn't sure that the real usage would clarify the issue...)
If I understand your problem correctly, as talked about in the comments, this should do it
from pprint import pprint
def slice_dict(d,a, b):
big_list = []
ret_dict = {}
# Make one big list of all numbers, tagging each number with the key
# of the dict they came from.
for k, v in d.iteritems():
for n in v:
big_list.append({k:n})
# Slice it
sliced = big_list[a:b]
# Put everything back in order
for k, v in d.iteritems():
for subd in sliced:
for subk, subv in subd.iteritems():
if k == subk:
if k in ret_dict:
ret_dict[k].append(subv)
else:
ret_dict[k] = [subv]
return ret_dict
d = {
'a': [1, 2, 3, 4],
'b': [5, 6, 7, 8, 9],
'c': [10, 11, 12, 13, 14]
}
x = slice_dict(d, 3, 11)
pprint(x)
$ python slice.py
{'a': [4], 'b': [5, 6], 'c': [10, 11, 12, 13, 14]}
The output is a little different from your example output, but that's because the dict was not ordered when it was passed to the function. It was a-c-b, that's why b is cut off at 6 and c is not cut off

Django get a QuerySet from array of id's in specific order

heres a quick one for you:
I have a list of id's which I want to use to return a QuerySet(or array if need be), but I want to maintain that order.
Thanks
Since Django 1.8, you can do:
from django.db.models import Case, When
pk_list = [10, 2, 1]
preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)])
queryset = MyModel.objects.filter(pk__in=pk_list).order_by(preserved)
I don't think you can enforce that particular order on the database level, so you need to do it in python instead.
id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
objects = dict([(obj.id, obj) for obj in objects])
sorted_objects = [objects[id] for id in id_list]
This builds up a dictionary of the objects with their id as key, so they can be retrieved easily when building up the sorted list.
If you want to do this using in_bulk, you actually need to merge the two answers above:
id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]
Otherwise the result will be a dictionary rather than a specifically ordered list.
Here's a way to do it at database level. Copy paste from: blog.mathieu-leplatre.info
:
MySQL:
SELECT *
FROM theme
ORDER BY FIELD(`id`, 10, 2, 1);
Same with Django:
pk_list = [10, 2, 1]
ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list)
queryset = Theme.objects.filter(pk__in=[pk_list]).extra(
select={'ordering': ordering}, order_by=('ordering',))
PostgreSQL:
SELECT *
FROM theme
ORDER BY
CASE
WHEN id=10 THEN 0
WHEN id=2 THEN 1
WHEN id=1 THEN 2
END;
Same with Django:
pk_list = [10, 2, 1]
clauses = ' '.join(['WHEN id=%s THEN %s' % (pk, i) for i, pk in enumerate(pk_list)])
ordering = 'CASE %s END' % clauses
queryset = Theme.objects.filter(pk__in=pk_list).extra(
select={'ordering': ordering}, order_by=('ordering',))
id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
sorted(objects, key=lambda i: id_list.index(i.pk))
Another better/cleaner approach can be
pk_list = [10, 2, 1]
sorted_key_object_pair = MyModel.objects.in_bulk(pk_list)
sorted_objects = sorted_key_object_pair.values()
Simple, clean, less code.