How to update a document in CouchDB - python

I have a list r which contains 12 lists as elements. Each list contains some elements (i[0] to i[5]) which are the same compare to other lists.
I tried only to insert unique documents so as result I should get 5 documents in the DB. If the document already exist then append i[6] and i[7] to chr.
import couchdb
# $ sudo systemctl start couchdb
# http://localhost:5984/_utils/
server = couchdb.Server()
try:
db = server.create("test")
except couchdb.http.ResourceConflict:
db = server["test"]
r = [["Test", "A", "B01", 828288, 1, 7, 'C', 5],
["Test", "A", "B01", 828288, 1, 7, 'T', 6],
["Test", "A", "B01", 171878, 3, 8, 'C', 5],
["Test", "A", "B01", 171878, 3, 8, 'T', 6],
["Test", "A", "B01", 871963, 3, 9, 'A', 5],
["Test", "A", "B01", 871963, 3, 9, 'G', 6],
["Test", "A", "B01", 1932523, 1, 10, 'T', 4],
["Test", "A", "B01", 1932523, 1, 10, 'A', 5],
["Test", "A", "B01", 1932523, 1, 10, 'X', 6],
["Test", "A", "B01", 667214, 1, 14, 'T', 4],
["Test", "A", "B01", 667214, 1, 14, 'G', 5],
["Test", "A", "B01", 667214, 1, 14, 'G', 6]]
_id = None
for i in r:
_id = str(i[5])
doc = {
'type': i[0],
'name': i[1],
'sub_name': i[2],
'pos': i[3],
's_type': i[4],
'_id': _id,
'chr':[]
}
doc['chr'].append({
"letter":i[6],
"no":i[7]
})
a = db.save(doc)
UPDATE
The first two lists in r contains the same fields (i[0] to i[5]). The final document for the two lists should like this:
{
"_id": "7",
"_rev": "1-bc0b4e6f3aa855a486225f4a0dcd76c8",
"sub_name": "B01",
"name": "A",
"pos": 828288,
"s_type": 1,
"chr": [
{
"letter": "C",
"no": 5
},
{
"letter": "T",
"no": 6
}
],
"type": "Test"
}
How is possible to update a document and append to a list a dict?

Is this the most efficient solution?
import couchdb
# $ sudo systemctl start couchdb
# http://localhost:5984/_utils/
server = couchdb.Server()
db = server.create("test")
# except couchdb.http.ResourceConflict:
#db = server["test"]
r = [["Test", "A", "B01", 828288, 1, 7, 'C', 5],
["Test", "A", "B01", 828288, 1, 7, 'T', 6],
["Test", "A", "B01", 171878, 3, 8, 'C', 5],
["Test", "A", "B01", 171878, 3, 8, 'T', 6],
["Test", "A", "B01", 871963, 3, 9, 'A', 5],
["Test", "A", "B01", 871963, 3, 9, 'G', 6],
["Test", "A", "B01", 1932523, 1, 10, 'T', 4],
["Test", "A", "B01", 1932523, 1, 10, 'A', 5],
["Test", "A", "B01", 1932523, 1, 10, 'X', 6],
["Test", "A", "B01", 667214, 1, 14, 'T', 4],
["Test", "A", "B01", 667214, 1, 14, 'G', 5],
["Test", "A", "B01", 667214, 1, 14, 'G', 6]]
# _id = None
for i in r:
_id = str(i[5])
doc = db.get(_id)
if doc is None:
doc = {
'type': i[0],
'name': i[1],
'sub_name': i[2],
'pos': i[3],
's_type': i[4],
'_id': _id,
'chr':[]
}
doc['chr'].append({
"letter":i[6],
"no":i[7]
})
else:
doc['chr'].append({
"letter":i[6],
"no":i[7]
})
db.save(doc)

Related

Sort list of lists based on max value at a specific index in Python without the use of prebuilt functions or methods

I have a list of lists and I want to learn how to sort the list by the element at index 1 but also sorted by the element at index 2 if index 1 returns the same number for two items.
I want to do this without the use of inbuilt functions and methods so that I can continue to develop my understanding of lists and how to manipulate them.
To recap:
I have a list of lists
Each sublist has the same number of elements
I am trying to sort them in descending order by creating a new unsorted list which is a copy of the original list (I don't want to modify the original unsorted list) and looping over the copy of the unsorted list to grab the highest number in (from index 1) and then appending that to a newly created sorted_lists variable
I then remove that list from the original unsorted list
I repeat the process until one by one the remaining lists with the highest value is added to the new sorted list and removed from the original list
I have tried a few different things but cannot get it to work. Any help would be appreciated.
# initialising list
food_list = (
["banana", 10, "f", "yellow"],
["apple", 12, "f", "red"],
["pear", 60, "f", "green"],
["mango", 5, "f", "yellow"],
["lettuce", 3, "v", "green"],
["beans", 20, "v", "green"],
["red capsicum", 1, "v", "red"],
["corn", 20, "v", "yellow"],
)
unsorted_food_list_copy = food_list
sorted_food_list = []
while len(unsorted_food_list_copy) != 0:
maximum = 0
for food in unsorted_food_list_copy:
if food[1] > maximum:
maximum = food[1]
sorted_food_list.append(maximum)
unsorted_food_list_copy.remove(maximum)
I have also tried this:
# initialising list
food_list = (
["banana", 10, "f", "yellow"],
["apple", 12, "f", "red"],
["pear", 60, "f", "green"],
["mango", 5, "f", "yellow"],
["lettuce", 3, "v", "green"],
["beans", 20, "v", "green"],
["red capsicum", 1, "v", "red"],
["corn", 20, "v", "yellow"],
)
unsorted_food_list_copy = food_list
sorted_food_list = []
while unsorted_food_list_copy:
min = unsorted_food_list_copy[1]
for x in unsorted_food_list_copy:
if x < min:
min = x
sorted_food_list.append(min)
unsorted_food_list_copy.remove(min)
In your code sample, you define food_list as a tuple while mentioning a list of list. In order to use list function like remove, copy or append, you need to add brackets around your lists.
Firstly, your food_list should be defined this way :
food_list = [
['banana', 10, 'f', 'yellow'],
['apple', 12, 'f', 'red'],
['pear', 60, 'f', 'green'],
['mango', 5, 'f', 'yellow'],
['lettuce', 3, 'v', 'green'],
['beans', 20, 'v', 'green'],
['red capsicum', 1, 'v', 'red'],
['corn', 20, 'v', 'yellow'],
]
Secondly you set up your minimum value before iterating over the list, you consider the 1st element of your list in order to start looking for a lower integer.
minValue = unsorted_food_list_copy[0]
Complete solution :
# initializing list
food_list = [
['banana', 10, 'f', 'yellow'],
['apple', 12, 'f', 'red'],
['pear', 60, 'f', 'green'],
['mango', 5, 'f', 'yellow'],
['lettuce', 3, 'v', 'green'],
['beans', 20, 'v', 'green'],
['red capsicum', 1, 'v', 'red'],
['corn', 20, 'v', 'yellow'],
]
unsorted_food_list_copy = food_list.copy()
sorted_food_list = []
for i in range(len(unsorted_food_list_copy)):
minValue = unsorted_food_list_copy[0]
for x in unsorted_food_list_copy:
if x[1] < minValue[1]:
minValue = x
sorted_food_list.append(minValue)
unsorted_food_list_copy.remove(minValue)
sorted_food_list_descending = sorted_food_list[::-1]
print(sorted_food_list_descending)
# Ouput
[['pear', 60, 'f', 'green'],
['corn', 20, 'v', 'yellow'],
['beans', 20, 'v', 'green'],
['apple', 12, 'f', 'red'],
['banana', 10, 'f', 'yellow'],
['mango', 5, 'f', 'yellow'],
['lettuce', 3, 'v', 'green'],
['red capsicum', 1, 'v', 'red']]
To do this in descending order you could do this:
food_list = [
['banana', 10, 'f', 'yellow'],
['apple', 12, 'f', 'red'],
['pear', 60, 'f', 'green'],
['mango', 5, 'f', 'yellow'],
['lettuce', 3, 'v', 'green'],
['beans', 20, 'v', 'green'],
['red capsicum', 1, 'v', 'red'],
['corn', 20, 'w', 'yellow'],
]
food_list_copy = food_list.copy()
new_list = []
while food_list_copy:
hi = food_list_copy[0]
pi = 0
for i, e in enumerate(food_list_copy[1:], 1):
if e[1] > hi[1]:
hi = e
pi = i
elif e[1] == hi[1]:
if e[2] > hi[2]:
hi = e
pi = i
new_list.append(hi)
food_list_copy.pop(pi)
print(new_list)
Output:
[['pear', 60, 'f', 'green'],
['corn', 20, 'w', 'yellow'],
['beans', 20, 'v', 'green'],
['apple', 12, 'f', 'red'],
['banana', 10, 'f', 'yellow'],
['mango', 5, 'f', 'yellow'],
['lettuce', 3, 'v', 'green'],
['red capsicum', 1, 'v', 'red']]
The pythonic way to sort a list according to a specify (user-defined) key is to use sort with the key parameter.
food_list = [
["banana", 10, "f", "yellow"],
["apple", 12, "f", "red"],
["pear", 60, "f", "green"],
["mango", 5, "f", "yellow"],
["lettuce", 3, "v", "green"],
["beans", 20, "v", "green"],
["red capsicum", 1, "v", "red"],
["corn", 20, "w", "yellow"],
]
# create a copy (you can also use `copy.deepcopy`) and sort
sorted_food_list = [list(i) for i in food_list]
sorted_food_list.sort(key=lambda i: (-i[1], i[2]))
output
[['pear', 60, 'f', 'green'],
['beans', 20, 'v', 'green'],
['corn', 20, 'w', 'yellow'],
['apple', 12, 'f', 'red'],
['banana', 10, 'f', 'yellow'],
['mango', 5, 'f', 'yellow'],
['lettuce', 3, 'v', 'green'],
['red capsicum', 1, 'v', 'red']]

Create a dictionary from 2 lists

I would like to create a dictionary based on the three lists I have:
Hier = ['A', 'C']
values = [10, 20]
All = ['A', 'B', 'C', 'D']
The results shall look like this:
{"A", 10, "B": "", "C": 20, "D":""}
Try:
Hier = ["A", "C"]
values = [10, 20]
All = ["A", "B", "C", "D"]
d = dict.fromkeys(All, "")
d.update(zip(Hier, values))
print(d)
Prints:
{'A': 10, 'B': '', 'C': 20, 'D': ''}
EDIT: removed dict() from .update

couchdb-python specify own _id failed

How is it possible to define own _id in couchdb-python (0.9), because when I tried '_id': i[5] I got the following error message?
$ python test3.py
828288
Traceback (most recent call last):
File "test3.py", line 42, in <module>
db.save(doc)
File "/home/mictadlo/.virtualenvs/unisnp/lib/python2.7/site-packages/couchdb/client.py", line 415, in save
func = _doc_resource(self.resource, doc['_id']).put_json
File "/home/mictadlo/.virtualenvs/unisnp/lib/python2.7/site-packages/couchdb/client.py", line 954, in _doc_resource
if doc_id[:1] == '_':
TypeError: 'int' object has no attribute '__getitem__'
Below is the script which is causing the above error:
from couchdb.mapping import Document, TextField, IntegerField, Mapping
from couchdb.mapping import DictField, ViewField, BooleanField, ListField
from couchdb import Server
# $ sudo systemctl start couchdb
# http://localhost:5984/_utils/
server = Server()
db = server.create("test")
r = [["Test", "A", "B01", 828288, 1, 7, 'C', 5],
["Test", "A", "B01", 828288, 1, 7, 'T', 6],
["Test", "A", "B01", 171878, 3, 8, 'C', 5],
["Test", "A", "B01", 171878, 3, 8, 'T', 6],
["Test", "A", "B01", 871963, 3, 9, 'A', 5],
["Test", "A", "B01", 871963, 3, 9, 'G', 6],
["Test", "A", "B01", 1932523, 1, 10, 'T', 4],
["Test", "A", "B01", 1932523, 1, 10, 'A', 5],
["Test", "A", "B01", 1932523, 1, 10, 'X', 6],
["Test", "A", "B01", 667214, 1, 14, 'T', 4],
["Test", "A", "B01", 667214, 1, 14, 'G', 5],
["Test", "A", "B01", 667214, 1, 14, 'G', 6]]
for i in r:
print i[3]
doc = {
'type': i[0],
'name': i[1],
'sub_name': i[2],
'pos': i[3],
's_type': i[4],
'_id': i[5],
'chr':[]
}
doc['chr'].append({
"letter":i[6],
"no":i[7]
})
db.save(doc)
It expects _id to be a string and you are passing a type of int. The error is caused by this line:
if doc_id[:1] == '_':
Because script is trying to slice an int object.
So change it to string type:
...
...
'_id': str(i[5]),
...

Python: Replacing values in dictionary with array

I want to replace the value of first key of list1 with the elements of list2. But the output with following code is:
output
list[21, 21, 22, 22]
[{'a': array([[22, 22, 3]]), 'i': 'stop', 'c': array([7, 8, 9]), 'b': array([4, 5, 6])}, {'a': array([[1, 2, 3]]), 'i': 'stop', 'c': array([7, 8, 9]), 'b': array([4, 5, 6])}]
my code
list1 = [{'a': array([(1,2,3)]), 'b': array([4,5,6]), 'i': 'stop', 'c': array([7,8,9])}, {'a': array([(1,2,3)]), 'b': array([4,5,6]), 'i': 'stop', 'c': array([7,8,9])}]
list2 = [ array([21, 22, 23]), array([25, 26, 27])]
list3=[]
for item in liste:
for key,value in item.iteritems():
if key == 'a':
list3.append(value)
list4=[]
for i in range(len(g_a)):
for j in range(len(list3)):
list3[0][0][j] = g_a[0][i]
list4.append(list3[0][0][j])
print list4
print list
I want to get this:
liste = [{'a': array([(21,22,23)]), 'b': array([4,5,6]), 'i': 'stop', 'c': array([7,8,9])}, {'a': array([(25,26,27)]), 'b': array([4,5,6]), 'i': 'stop', 'c': array([7,8,9])}]
Where is the error? Thank you very much in advance!
Here is a dict comprehension in python 2.7 with a one-liner:
[{k: d[k] if k != 'a' else list2[i] for k in d} for i, d in enumerate(list1)]
It gives:
[{'a': [21, 22, 23], 'i': 'stop', 'c': [7, 8, 9], 'b': [4, 5, 6]}, {'a': [25, 26, 27], 'i': 'stop', 'c': [7, 8, 9], 'b': [4, 5, 6]}]

What is the difference between json.dumps/loads and tornado.escape.json_encode/json_decode?

It seems they are behaving exactly the same way.
>>> data
[('a', 'b'), {'a': 1, 'b': 2}, ['a', 'b'], 'a', 'b']
>>> json.dumps(data)
'[["a", "b"], {"a": 1, "b": 2}, ["a", "b"], "a", "b"]'
>>> tornado.escape.json_encode(data)
'[["a", "b"], {"a": 1, "b": 2}, ["a", "b"], "a", "b"]'
>>> json.loads(json.dumps(data))
[[u'a', u'b'], {u'a': 1, u'b': 2}, [u'a', u'b'], u'a', u'b']
>>> tornado.escape.json_decode(json.dumps(data))
[[u'a', u'b'], {u'a': 1, u'b': 2}, [u'a', u'b'], u'a', u'b']
Sometimes it's useful to read the source code:
def json_encode(value):
return json.dumps(value).replace("</", "<\\/")
def json_decode(value):
return json.loads(to_basestring(value))
def to_basestring(value):
if isinstance(value, _BASESTRING_TYPES):
return value
assert isinstance(value, bytes_type)
return value.decode("utf-8")
to_basestring is mostly needed for python 3.x to ensure the value has type str, not bytes, because json.loads can't deal with the latter.

Categories