How to make a list from a query? [duplicate] - python

This question already has answers here:
How to modify list entries during for loop?
(10 answers)
Closed 11 months ago.
I run a query and want to make a list from this query. I only need those select items, which I got, but I can't get rid of "," in lst.
I tried replace but it didn't work.
query = """
select
supplier_no_and_name,
accepted,
rejected,
pending,
tdc
from edl_current.supplier_warranty_cost_recovery_warranty_alteryx
where claim_date > "2021-01-01"
"""
lst = query.split()
lst = lst[1-len(lst):len(lst)-13]
for i in range(len(lst)):
lst[i].replace(',',"")
print(lst)
The output is following:
['supplier_no_and_name,', 'accepted,', 'rejected,', 'pending,', 'tdc']

replace method has a return value which is string meaning it doesn't update the original value itself. So, you need to assign with a new value using same variable or anything.
lst[i] = lst[i].replace(',',"")

str.rstrip() and list comprehension would be simpler.
# for i in range(len(lst)):
# lst[i]=lst[i].replace(',',"")
l = [ x.rstrip(',') for x in lst ]
lst = l[:l.index('tdc')+1] # for making same output.

Try this:-
query = """
select
supplier_no_and_name,
accepted,
rejected,
pending,
tdc
from edl_current.supplier_warranty_cost_recovery_warranty_alteryx
where claim_date > "2021-01-01"
"""
lst = query.split()
lst = lst[1-len(lst):len(lst)-13]
for i in range(len(lst)):
lst[i] = lst[i].replace(',', "")
d = ' '.join(lst)
print(d)
Things you should follow next time you ask questions on stack overflow.
Add the expected output in proper format.
Show the things that you've tried in the post.
Frame your question properly and always add error message if found any.
Most importantly search the question on stack overflow before posting it
85 % of time you'll get the answers without posting.

Your current solution is super brittle in that you need to know in advance the exact number of words in your SQL statement. I think you want to try to be a little more flexible and pick out the SELECT and FROM clauses:
query = """
select
supplier_no_and_name,
accepted,
rejected,
pending,
tdc
from edl_current.supplier_warranty_cost_recovery_warranty_alteryx
where claim_date > "2021-01-01"
"""
query_parts = [
p.strip(",")
for p
in query.replace("\n", " ").split()
if p
]
select_index = query_parts.index("select")
from_index = query_parts.index("from")
lst = query_parts[select_index+1 : from_index]
print(lst)
This should give you:
['supplier_no_and_name', 'accepted', 'rejected', 'pending', 'tdc']
Without being sensitive to the number of words or columns.

Since strings are immutable, their replace() method returns a new string with the modifications as opposed to doing them "in place". This means you have to explicitly replace the values in the list.
for i, value in enumerate(lst):
lst[i] = value.replace(',', '')

Related

Find the index of a value in a list, that is also inside of a string, using the any() function [duplicate]

This question already has answers here:
Get the first item from an iterable that matches a condition
(18 answers)
Closed 1 year ago.
Sorry if the question is a little confusing, but basically I have the following data:
useable = ['osc_1_', 'osc_2_', 'osc_3_', 'sample_', 'filter_1_', 'filter_2_', 'filter_fx_', 'lfo_1_', 'lfo_2_', 'lfo_3_', 'lfo_4_', 'lfo_5_', 'lfo_6_', 'lfo_7_', 'lfo_8_', 'random_1_', 'random_2_', 'random_3_', 'random_4_', 'env_1_', 'env_2_', 'env_3_', 'env_4_', 'env_5_', 'env_6_', 'chorus_', 'compressor', 'delay', 'distortion', 'phaser', 'flanger', 'reverb', 'equalizer']
I also have a string value: x = 'filter_fx_formant_x'
I'm using the following function to return 'True' if x contains a value that can be found in useable,
if any(useable in x for useable in useable):
ex: 'filter_fx_' is in both a substring of x and a value in useable.
Now here's my question: How can I get the index value of the item that can be found in a substring of x?
Is there a better way other than any()? Am I missing something obvious? Let me know if you can think of anything.
this You can use if You want to get the index:
useable = ['osc_1_', 'osc_2_', 'osc_3_', 'sample_', 'filter_1_', 'filter_2_', 'filter_fx_', 'lfo_1_', 'lfo_2_', 'lfo_3_', 'lfo_4_', 'lfo_5_', 'lfo_6_', 'lfo_7_', 'lfo_8_', 'random_1_', 'random_2_', 'random_3_', 'random_4_', 'env_1_', 'env_2_', 'env_3_', 'env_4_', 'env_5_', 'env_6_', 'chorus_', 'compressor', 'delay', 'distortion', 'phaser', 'flanger', 'reverb', 'equalizer']
x = 'filter_fx_formant_x'
for index, item in enumerate(useable):
if item in x:
print(index, item)
If your concern is to use any(), one way to implement your logic would be by the combination of map and str.contains()
any(map(x.__contains__, useable))
Output:
True
if you just want to get the first index if x contains substring from the list, you can implement same thing in an if conditional
>>mask = list(map(x.__contains__, useable))
>>if any(mask):
print(mask.index(True))
6
This is what next+enumerate allows:
try:
idx, found = next((i, useable) for i, useable in enumerate(useables) if useable in x):
except StopIteration:
# No hits found
else:
# idx is now the index of the first item to hit, found is the value
If you're guaranteed to have a hit for whatever reason, the try/except/else isn't needed.
It should be like this instead:
if (any(substring in x for substring in useable)):

Bug free version of string substitution [duplicate]

This question already has answers here:
Replacing multiple similar strings
(1 answer)
How to replace two things at once in a string?
(6 answers)
How to replace multiple substrings of a string?
(28 answers)
Closed 4 years ago.
I am trapped in a quite straight forward problem, but after some tweak, I simply cannot find an easy and efficient algorithm to do this.
So basically I have a string, which contains certain elements, for instance:
l = "test %1, %13, %14, %15"
And a map:
dict = {"%1": "%33", "%13": "%14", "%14", "%15", "%15": "%17"}
And I would like to do the following stuff:
for k in dict.keys():
l = l.replace(k, dict[k])
So what I am expecting is:
l = "test %33, %14, %15, %17"
But apparently this is not feasible, since there are some conflict between keys and values. So the above code would output:
l = "test %33, %17, %17, %17"
Sorry for such native problem, but how should I solve this and get my expected output? Note that the length of each key/value is not fixed, so I cannot do something like:
m_idx = l_copy.find(key)
l = l[:m_idx] + dict[key] + l[m_idx+len(key):]
Because the length is not fixed, the above code is still buggy.
Am I clear on this? Any suggestion would be appreciated very much!
======= update
So all keys follow this pattern of %[0-9]+.
You can use re.sub with a lambda:
import re
l = "test %1, %13, %14, %15"
_dict = {"%1": "%33", "%13": "%14", "%14":"%15", "%15": "%17"}
new_l = re.sub('%\d+', lambda x:_dict[x.group()], l)
Output:
'test %33, %14, %15, %17'
You can use dict.get to prevent a KeyError by providing a default value should the key not be present in _dict:
new_l = re.sub('%\d+', lambda x:_dict.get(x.group(), x.group()), l)

Make this code look more elegant [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am absolutly new in python and in programing, I made this bifid cipher, I'd like to hear opinions about how to improve and make it look more elegant, thanks in advance.
I been taking courses in Codecademy and Udacity, and I've learn quite a lot.
import itertools
#Genera coodernadas-Generate Coordinates
coordinates = [[x,y] for x in range(1,6) for y in range(1,6)]
#Genera alfabeto-Generate Alphabet
alfa = []
for i in range(97,123):
alfa.append(chr (i))
alfa.remove("i")
#Genera diccionario de coordenadas y alfabeto - Generate dictionary and coordinates alphabet
alfacor = {}
alfacor = dict(zip(alfa,coordinates))
#Leer Txt - Read txt
document = open("Z:\\R\\Desktop\\BIFIDO\\easy.txt")
contenido = document.read()
print (contenido)
document.close()
#Encripta fase1 - Get's coordinates of txt
encripta = []
for e in contenido:
encripta.append(alfacor[e])
#Unir lista encripta - Merge content of encropita in a new list
merged = list(itertools.chain.from_iterable(encripta))
#Divido lista merge en partes iguales - Divide meged list to get new coordinates
B = merged[:len(merged)/2]
C = merged[len(merged)/2:]
#Unir B y C - Zip B and C to get a new list of coordinates
zipped = zip(B,C)
#Make a new list from zipped to convert from tuple to list
final_list = [list(elem) for elem in zipped]
#Convert contect of alfacor to tuples
inv_alfacor = {}
for letter, coordinate in alfacor.iteritems():
inv_alfacor[tuple(coordinate)] = letter
#Substitude coordinates of final_list from elements of inv_alfacor
encripta_f = []
for element in final_list:
element = tuple(element)
if element in inv_alfacor:
encripta_f.append(inv_alfacor[element])
print "Tu palabra ",encripta_f
Other than perhaps using comprehensions and avoid the unnecessary tuple -> list -> tuple conversions, reduce the number of intermediate variables then it might be slightly easier to read. I would also consider making it a function that you pass in a string and an encrypted string is returned:
from itertools import chain, product
def bifid(data):
# Leave coordinates as tuples and appropriate use of itertools.product
coordinates = product(range(1, 6), repeat=2)
# Using comprehensions and generators to construct the list/dicts vs loops
# Leave alfa as a generator as it is only used once
alfa = (chr(i) for i in range(97, 123) if chr(i) != 'i')
alfacor = dict(zip(alfa, coordinates))
inv_alfacor = {coordinate: letter for letter, coordinate in alfacor.iteritems()}
encripta = (alfacor[e] for e in data)
merged = list(chain(*encripta))
final_list = zip(merged[:len(merged)//2], merged[len(merged)//2:])
return "".join(inv_alfacor[e] for e in final_list if e in inv_alfacor)
# Use with it closes automatically and handles exceptions correctly
with open("Z:\\R\\Desktop\\BIFIDO\\easy.txt") as document:
data = document.read()]
print "Tu palabra: {}".format(bifid(data))
Output:
"helloworld" -> Tu palabra: kmcyobnalt
Use with statement
You can read more in python docs or in this article Understanding Python's "with" statement
Suggested modification:
#Leer Txt - Read txt
with open("Z:\\R\\Desktop\\BIFIDO\\easy.txt", "r") as document:
contenido = document.read()
print (contenido)
Use list comprehensions
More info in Python docs or in the tutorial Python Tutorial: List Comprehensions
Suggested modification:
#Genera alfabeto-Generate Alphabet
alfa = [chr(i) for i in xrange(97, 123) if chr(i) != "i"]
(Note, please, this change also includes a condition in the list comprehension - example at SO question)
And also:
#Encripta fase1 - Get's coordinates of txt
encripta = [alfacor[e] for e in contenido]
Use generators
The first thing you can start with is following. When you write a list comprehension and you know you are going to iterate only one item of the list a time, change the brackets from [] to (). This is really simplified but it is the first thing you can do. Another related tip, when you use range(x) just like for i in range(x), use xrange(x) instead. xrange is a generator version of range.
More info in Python Wiki
Suggested change:
#Make a new list from zipped to convert from tuple to list
final_list = (list(elem) for elem in zipped)
Printing
In this case, using the print you used is fine, but have a look at string formatting.
More in Python docs and a few examples here.
Possible change:
print "Tu palabra {}".format(encripta_f)
You don't need to initialize all the variables.
You don't need to initialize alfacor dictionary when you assign a completely new value to the variable. However, you need to initialize variable when you work with it later.
Thus there is a difference between
# no need for initialization
alfacor = {}
# because you assign a new value here to the variable `alfacor`
alfacor = dict(zip(alfa,coordinates))
and this:
# you need to initialize this
alfacor = {}
# because you are working with the empty dictionary here
alfacor["my_key"] = "my_value"

Slicing a List of Strings

Am I able to slice a list of strings? If it is possible could anyone please tell me how to do it so that I am able to print out a particular string instead of the five that make up the list.
Cheers.
eg.
mylist = ['apples' 'oranges' 'lemons' 'cucumbers' 'bananas']
print 'orange'
** The programming language i am using is python. Every time I code it mylist[2] it comes out as an error. The list I am using is extracting the strings from a html rss feed. Each string is a new news heading. However, even when it updates constantly there are always 5 strings in the list and it tells me list index out of range. But if I just print the entire list it works fine**
#URLS for RSS Feeds
url_national = 'http://feeds.news.com.au/public/rss/2.0/news_national_3354.xml'
url_sport = 'http://feeds.news.com.au/public/rss/2.0/news_sport_3168.xml'
url_world = 'http://feeds.news.com.au/public/rss/2.0/news_theworld_3356.xml'
url_technology = 'http://feeds.news.com.au/public/rss/2.0/news_tech_506.xml'
def headlines (url):
web_page = urlopen(url)
html_code = web_page.read()
web_page.close()
return findall(r'<item><title>([^<]*)</title>', html_code)
#headlines list
list_national = [headlines(url_national)]
list_sport = [headlines(url_sport)]
list_world = [headlines(url_world)]
list_technology = [headlines(url_technology)]
def change_category():
if label_colour.get() == 'n':
changeable_label['text'] = list_national #here I would slice it but it doesn't work
elif label_colour.get() == 's':
changeable_label['text'] = list_sport
elif label_colour.get() =='w':
changeable_label['text'] = list_world
else:
changeable_label['text'] = list_technology
the reason I need to slice it into individual heading is so when the radio button is pressed for my GUI it prints them in a numbered list on the label not all just running on one line next to them - sorry i hope that makes sense
What language are you using here? Usually you can use an index to access a particular entry in a list. For example:
print myList[1]
Commas are missing in your list creation. You have to do it like this:
mylist = ['apples', 'oranges', 'lemons', 'cucumbers', 'bananas']
And you will be able to work with your list
mylist[0] # 'apples'
mylist[-1] # 'bananas'
mylist[2] # 'lemons'
I think the error you are getting is something like this:
mylist = ['apples' 'oranges' 'lemons' 'cucumbers' 'bananas']
print mylist[5]
IndexError: list index out of range
The reason is the elements in a list are indexed from 0 not 1.
The mylist has 5 elements starting from 0 to 4. So when you call print mylist[5] it will definitely give an error as there is no 6th element in the list.
Here is the official doc regarding list please have a look.
I hope it was helpful!

Having problems in extracting duplicates

I am stumped with this problem, and no matter how I get around it, it is still giving me the same result.
Basically, supposedly I have 2 groups - GrpA_null and GrpB_null, each having 2 meshes in them and are named exactly the same, brick_geo and bars_geo
- Result: GrpA_null --> brick_geo, bars_geo
But for some reason, in the code below which I presume is the one giving me problems, when it is run, the program states that GrpA_null has the same duplicates as GrpB_null, probably they are referencing the brick_geo and bars_geo. As soon as the code is run, my children geo have a numerical value behind,
- Result: GrpA_null --> brick_geo0, bars_geo0, GrpB_null1 --> brick_geo, bars_geo1
And so, I tried to modify the code such that it will as long as the Parent (GrpA_null and GrpB_null) is different, it shall not 'touch' on the children.
Could someone kindly advice me on it?
def extractDuplicateBoxList(self, inputs):
result = {}
for i in range(0, len(inputs)):
print '<<< i is : %s' %i
for n in range(0, len(inputs)):
print '<<< n is %s' %n
if i != n:
name = inputs[i].getShortName()
# Result: brick_geo
Lname = inputs[i].getLongName()
# Result: |GrpA_null|concrete_geo
if name == inputs[n].getShortName():
# If list already created as result.
if result.has_key(name):
# Make sure its not already in the list and add it.
alreadyAdded = False
for box in result[name]:
if box == inputs[i]:
alreadyAdded = True
if alreadyAdded == False:
result[name].append(inputs[i])
# Otherwise create a new list and add it.
else:
result[name] = []
result[name].append(inputs[i])
return result
There are a couple of things you may want to be aware of. First and foremost, indentation matters in Python. I don't know if the indentation of your code as is is as intended, but your function code should be indented further in than your function def.
Secondly, I find your question a little difficult to understand. But there are several things which would improve your code.
In the collections module, there is (or should be) a type called defaultdict. This type is similar to a dict, except for it having a default value of the type you specify. So a defaultdict(int) will have a default of 0 when you get a key, even if the key wasn't there before. This allows the implementation of counters, such as to find duplicates without sorting.
from collections import defaultdict
counter = defaultdict(int)
for item in items:
counter[item] += 1
This brings me to another point. Python for loops implement a for-each structure. You almost never need to enumerate your items in order to then access them. So, instead of
for i in range(0,len(inputs)):
you want to use
for input in inputs:
and if you really need to enumerate your inputs
for i,input in enumerate(inputs):
Finally, you can iterate and filter through iterable objects using list comprehensions, dict comprehensions, or generator expressions. They are very powerful. See Create a dictionary with list comprehension in Python
Try this code out, play with it. See if it works for you.
from collections import defaultdict
def extractDuplicateBoxList(self, inputs):
counts = defaultdict(int)
for input in inputs:
counts[input.getShortName()] += 1
dup_shns = set([k for k,v in counts.items() if v > 1])
dups = [i for i in inputs if input.getShortName() in dup_shns]
return dups
I was on the point to write the same remarks as bitsplit, he has already done it.
So I just give you for the moment a code that I think is doing exactly the same as yours, based on these remarks and the use of the get dictionary's method:
from collections import defaultdict
def extract_Duplicate_BoxList(self, inputs):
result = defaultdict()
for i,A in enumerate(inputs):
print '<<< i is : %s' %i
name = A.getShortName() # Result: brick_geo
Lname = A.getLongName() # Result: |GrpA_null|concrete_geo
for n in (j for j,B in enumerate(inputs)
if j!=i and B.getShortName()==name):
print '<<< n is %s' %n
if A not in result.get(name,[])):
result[name].append(A)
return result
.
Secondly, as bitsplit said it, I find your question ununderstandable.
Could you give more information on the elements of inputs ?
Your explanations about GrpA_null and GrpB_null and the names and the meshes are unclear.
.
EDIT:
If my reduction/simplification is correct, examining it , I see that What you essentially does is to compare A and B elements of inputs (with A!=B) and you record A in the dictionary result at key shortname (only one time) if A and B have the same shortname shortname;
I think this code can still be reduced to just:
def extract_Duplicate_BoxList(inputs):
result = defaultdict()
for i,A in enumerate(inputs):
print '<<< i is : %s' %i
result[B.getShortName()].append(A)
return result
this may be do what your looking for if I understand it, which seems to be comparing the sub-hierarchies of different nodes to see if they are they have the same names.
import maya.cmds as cmds
def child_nodes(node):
''' returns a set with the relative paths of all <node>'s children'''
root = cmds.ls(node, l=True)[0]
children = cmds.listRelatives(node, ad=True, f=True)
return set( [k[len(root):] for k in children])
child_nodes('group1')
# Result: set([u'|pCube1|pCubeShape1', u'|pSphere1', u'|pSphere1|pSphereShape1', u'|pCube1']) #
# note the returns are NOT valid maya paths, since i've removed the root <node>,
# you'd need to add it back in to actually access a real shape here:
all_kids = child_nodes('group1')
real_children = ['group1' + n for n in all_kids ]
Since the returns are sets, you can test to see if they are equal, see if one is a subset or superset of the other, see what they have in common and so on:
# compare children
child_nodes('group1') == child_nodes('group2')
#one is subset:
child_nodes('group1').issuperset(child_nodes('group2'))
Iterating over a bunch of nodes is easy:
# collect all the child sets of a bunch of nodes:
kids = dict ( (k, child_nodes(k)) for k in ls(*nodes))

Categories