Is there a way to convert a list of tuples into a single tuple? I have received a list of tuples from cursor.fetchall() but would like to make this into a single tuple:
curr_table_columns = cursor.fetchall()
For example:
[(u'w_id',), (u'w_name',), (u'w_street',)]
becomes
[(u'w_id', u'w_name', u'w_street')]
With itertools.chain, it's trivial. from itertools import chain and you can do either:
[tuple(chain.from_iterable(curr_table_columns))]
or:
[tuple(chain(*curr_table_columns))]
The former is preferred for long or unbounded iterable inputs (though don't wrap in tuple for unbounded!); for a small input (particularly one that's already a list or tuple), the latter is slightly slower, but fine. Either one is going to be significantly faster than a genexpr and indexing for inputs of any size at all.
Try this:
a=[(u'w_id',), (u'w_name',), (u'w_street',)]
print [tuple([i[0] for i in a])]
Output:
[(u'w_id', u'w_name', u'w_street')]
Not efficient*, but it is simple:
>>> ts = [(u'w_id',), (u'w_name',), (u'w_street',)]
>>> sum(ts, ())
('w_id', 'w_name', 'w_street')
So, just wrap it in a list if you must:
>>> result = [sum(ts, ())]
>>> result
[('w_id', 'w_name', 'w_street')]
*Warning: scales quadratically. Some might be inclined to let is slide for joining some column names into a single container. Definitely don't try to process millions of tuples this way.
Use itertools solution for linear time.
This function can convert listWidgets item into single tuple and also convert multiple element of tuple into single element tuple : Used for Sqlite3 and data query from listwidgets.
def tuple_converter(self,item):
target = ''
for i in item:
target += i + " "
target = target.rstrip()
target = tuple(target.split(","))
return target
#syntax name = tuple_converter(tuple((item).split()))
'''
Related
I have a list in Python as
list_data = [('a','b',5),('aa','bb',50)]
and some variables:
a = ('a','b','2')
c = ('aaa','bbb','500')
Now how can I search if a is already there in list_data?
If yes add 2 to the value of a, if not append to list_data?
The result should be as
list_data = [('a','b',7),('aa','bb',50),('aaa','bbb','500')]
Actually, this question is a good way to several demonstrate Pythonic ways of doing things. So lets see what we can do.
In order to check if something is in python list you can just use operator in:
if a in list_data:
do_stuff()
But what you ask is a bit different. You want to do something like a search by multiple keys, if I understand correctly. In this case you can 'trim' your tuple by discarding last entry.
Slicing is handy for this:
value_trimmed = value[:-1]
Now you can make a list of trimmed tuples:
list_trimmed = []
for a in list_data:
list_trimmed.append(a[:-1])
And then search there:
if a[:-1] in list_trimmed:
do_smth()
This list can be constructed in a less verbose way using list_comprehension:
list_trimmed = [item[:-1] for item in list_data]
To find where your item exactly is you can use index() method of list:
list_trimmed.index(a[:-1])
This will return index of a[:-1] first occurrence in list_trimmed or throw if it cant be found. We can avoid explicitly checking if item is in the list, and do the insertion only if the exception is caught.
Your full code will look like this:
list_data = [('a','b',5), ('aa','bb',50)]
values_to_find = [('a','b','2'), ('aaa','bbb','500')]
list_trimmed = [item[:-1] for item in list_data]
for val in values_to_find:
val_trimmed = val[:-1]
try:
ind = list_trimmed.index(val_trimmed)
src_tuple = list_data[ind]
# we can't edit tuple inplace, since they are immutable in python
list_data[ind] = (src_tuple[0], src_tuple[1], src_tuple[2]+2)
except ValueError:
list_data.append(val)
print list_data
Of course, if speed or memory-efficiency is your main concern this code is not very appropriate, but you haven't mentioned these in your question, and that is not what python really about in my opinion.
Edit:
You haven't specified what happens when you check for ('aaa','bbb','500') second time - should we use the updated list and increment matching tuple's last element, or should we stick to the original list and insert another copy?
If we use updated list, it is not clear how to handle incrementing string '500' by 2 (we can convert it to integer, but you should have constructed your query appropriately in the first place).
Or maybe you meant add last element of tuple being searched to the tuple in list if found ? Please edit your question to make it clear.
I have at data that looks like this:
Probes FOO BAR
1452463_x_at 306.564 185.705
1439374_x_at 393.742 330.495
1426392_a_at 269.850 209.931
1433432_x_at 636.145 487.012
In the second column it contain white space after tab.
import sys
import csv
import pprint
with open('tmp.txt') as tsvfile:
tabreader = csv.reader(tsvfile,delimiter="\t");
for row in tabreader:
#val = s.strip() for s in [row[1:3]]
val = row[1:3]
print val
Here is the code that prints this:
['FOO', 'BAR']
['306.564 ', '185.705']
['393.742 ', '330.495']
['269.850 ', '209.931']
['636.145 ', '487.012']
Now what I want to do is to strip the white space on the fly while iterating through the row,
without storing the values in temporary array.
Especially with this line:
#val = s.strip() for s in [row[1:3]]
But why it failed? What's the way to do it
You've got the syntax wrong. You want a list-comprehension:
val = [s.strip() for s in row[1:3]]
Now, I'm not exactly sure what you want, but I have created a new list. There's no clean1 way around that.
1You could use an explicit loop and strip the values while re-assigning them to the original list, but ... Yuck...
If you really want to, you can mutate the row in place this way:
row[:] = [s.strip() for s in row[1:3]]
But I'm not completely sure what advantage you'd get here.
There's a concept of generator expressions in python. This is a lazy-evaluated version of list-comprehension that does not create a resulting list immediately. However, ordinary print does not cause the generator to evaluate, so you'll need to convert it to list before printing.
So, with your code it should look like (note round brackets)
for row in tabreader:
val = (s.strip() for s in row[1:3])
print list(val)
Using generator expression doesn't realy have any advantages over list comprehension in your example as you are going to print the result right away. It could be very handy if you need to do some additional processing on huge lists, reducing memory footprint due to the fact that generator expression does not allocate memory required to hold results.
In two words: list-comprehension works like range (allocates the list and fills it with data right away), generator expression works like xrange (generates next item on-demand)
I want to split a inner string in order to get every item, the string is into a [()] structure,the object to process could be something like:
[(u'|name1|name2|name3|123|124|065|',)]
or
[(u'|name1|',)]
or
[(u'')]
or even
false
To get the items from the string I only need:
mystring.split('|')
But I think that my final approach is ugly and error-prone:
mylist[0][0].split('|')
How can I get a items list in a clean and pythonic way?
I think your approach is correct.
But what about the first and last elements of split('|') result?. They are empty because your strings starts and ends with a '|'.
You could use list comprehension.
[name for name in mylist[0][0].split('|') if name]
Or striping the string before:
mylist[0][0].strip('|').split('|')
Just do some previous checking.
If the string can be nested at not constant depth, just wrap the extraction in a loop until it is instance of basestring.
def split(container):
if not container:
return []
return container[0][0].split('|')
I agree that you're getting the best you can, but if you just want a different (equivalent) way of doing it,
from operator import itemgetter
f = itemgetter(0)
f(f(mylist)).split('|')
Have table want to use numpy to slice into sections
table = ['212:3:0:70.13911:-89.85361:3', '212:3:1:70.28725:-89.77466:7', '212:3:2:70.39231:-89.74908:9', '212:3:3:70.48806:-89.6414:11', '212:3:4:70.60366:-89.51539:14', '212:3:5:70.60366:-89.51539:14', '212:3:6:70.66518:-89.4048:16']
t = np.asarray (table, dtype ='object')
Want to use numpy to slice all........ 212:3:0, 212:3:1 as k.
Want all '212:3:0:70.13911:-89.85361:3','212:3:1:70.28725:-89.77466:7' as v
into a dictionany dict (k,v). I dont want to use a for-loop to do this...
I have done this as for loop its slow.
NOTE: the row has ":", but the ":" does mean the dict ':'.
Basics of dict comprehensions
To convert something into a dict, you need to make it into an iterable that generates 2-sequences (anything that generates a sequence of two elements), like [[1,2],[3,4]] or [(1,2),(3,4)] or zip([1,2,3,4], [5,6,7,8]))
E.g.
>>> mylst = [(1,2), (3,4), (5,6)]
>>> print dict(mylst)
{1:2, 3:4, 5:6}
so you need to split each of your strings in such a way that you produce a
tuple. say you've already written a function that does this, called
split_item that takes in a two strings and returns a tuple. You could then
write a generator expression like the following so that you don't need to load
everything into memory until you create the dict.
def generate_tuples(table):
length = len(table)
for i in range(1, length - 1):
yield split_item(table[i-1], table[i])
then just call the dict builtin on your generator function.
>>> dict(generate_tuples(table))
Since you say you already wrote this with a for-loop, I'm guessing you already have a split_items function written.
Making it fast
Here's a guide to high-performance Python, written by Ian Ozsvald, that can help you experiment with other ways to increase the speed of processing. (credit to #AndrewWalker 's SO post here)
Is this what you're after?
dict( (t.rsplit(':', 3)[0], t) for t in table ) )
.append
Function adds elements to the list.
How can I add elements to the list? In reverse? So that index zero is new value, and the old values move up in index?
What append does
[a,b,c,d,e]
what I would like.
[e,d,c,b,a]
Thank you very much.
Suppose you have a list a, a = [1, 2, 3]
Now suppose you wonder what kinds of things you can do to that list:
dir(a)
Hmmmm... wonder what this insert thingy does...
help(a.insert)
Insert object before index, you say? Why, that sounds a lot like what I want to do! If I want to insert something at the beginning of the list, that would be before index 0. What object do I want to insert? Let's try 7...
a.insert(0, 7)
print a
Well, look at that 7 right at the front of the list!
TL;DR: dir() will let you see what's available, help() will show you how it works, and then you can play around with it and see what it does, or Google up some documentation since you now know what the feature you want is called.
It would be more efficient to use a deque(double-ended queue) for this. Inserting at index 0 is extremely costly in lists since each element must be shifted over which requires O(N) running time, in a deque the same operation is O(1).
>>> from collections import deque
>>> x = deque()
>>> x.appendleft('a')
>>> x.appendleft('b')
>>> x
deque(['b', 'a'])
Use somelist.insert(0, item) to place item at the beginning of somelist, shifting all other elements down. Note that for large lists this is a very expensive operation. Consider using deque instead if you will be adding items to or removing items from both ends of the sequence.
Using Python's list insert command with 0 for the position value will insert the value at the head of the list, thus inserting in reverse order:
your_list.insert(0, new_item)
You can do
your_list=['New item!!']+your_list
But the insert method works as well.
lst=["a","b","c","d","e","f"]
lst_rev=[]
lst_rev.append(lst[::-1])
print(lst_rev)
Here's an example of how to add elements in a list in reverse order:
liste1 = [1,2,3,4,5]
liste2 = list()
for i in liste1:
liste2.insert(0,i)
Use the following (assuming x is what you want to prepend):
your_list = [x] + your_list
or:
your_list.insert(0, x)