Making a list from mainlist and from subslists
As chepner said, try write your own code without list comprehension and then modify your own code.
def pyramid(base, char):
return [ ['']*num_empty + [char]*num_char + ['']*num_empty for num_empty, num_char in enumerate(list(range(base, 0, -2)))][::-1]
I'd recommend breaking up the problems into two steps:
Generate the list of pyramid bricks (without the empty spaces)
Add in the empty spaces (as needed) to each element of that list
As for Step 1, you can easily accomplish it with this function:
def pyramid(base, char):
result = [[char] * i for i in range(1, base+1, 2)]
return result
Do you see what it's doing? It's looping through a range of odd numbers, and for each number, it is constructing a list of chars. Each constructed list will be an element of the returned result list.
So if you call pyramid(5, 'A'), you'll get:
[['A'], ['A', 'A', 'A'], ['A', 'A', 'A', 'A', 'A']]
This solution does not account for the empty spaces, however. To handle those empty spaces, you could either:
Run the result through a second list comprehension, or:
Edit the first (and only) list comprehension to include the proper number of spaces at the beginning and end of each sub-list.
I'll let you decide how to implement this for yourself. I hope this helps!
Related
I have a list that looks like :
mylist=[[["A","B"],["A","C","B"]],[["A","D"]]]
and I want to return :
mylist=[["A","B"],["A","C","B"],["A","D"]]
Using the split() function returns an error of :
list object has no attribute split
Therefore, I am unsure how I should split the elements of this list.
Thanks!
I am not sure why you think splitting will do any good for you; after all, you are -- if anything -- merging the second layer lists. But flattenening by one level can be done by a comprehension:
mylist = [inner for outer in mylist for inner in outer]
# [['A', 'B'], ['A', 'C', 'B'], ['A', 'D']]
One util to (maybe a matter of taste) simplify this is itertools.chain:
from itertools import chain
mylist = list(chain(*mylist))
Use for-loop in order to do this.
Here is an example code:
output = []
for list_element in my_list:
for single_list in list_element:
output.append(single_list)
I have a list of string like this -
list = ["A","V","C,"D",X","Y","V_RT","D_RT"]
I want to reorder the strings with suffix "_RT" right after the parent string(string without the suffix).
For example, the above string should become something like this -
list = ["A","V","V_RT","C,"D","D_RT",X","Y"] #notice how the strings with _RT moved after the string without _RT.
My approach-
Right now I am finding the strings with _RT, then searching the index of the parent string without _RT and then inserting it there. Finally, deleting the original prefixed string.
The above approach works but I believe there must be some short(one-two liner way) of doing the required which I don't know.
Please help.
Thanks.
EDIT
I forgot to mention but can't change the order of appearance. After "A", there will be "V" then "V_RT", "C", "D", "D_RT", etc. The strings are not necessarily of length 1. The above is just an example.
Another approach using for-loop
Check if current element + '_RT' is in original list
if True add current element and current element + '_RT' to the new list
if False and also if substring '_RT' is not in current element add the element to the new list
Code:
l = ["A","V","C","D","X","Y","V_RT","D_RT"]
l2 = []
for x in l:
if x+'_RT' in l:
l2+=[x, x+'_RT']
elif '_RT' not in x:
l2.append(x)
print(l2)
Output:
['A', 'V', 'V_RT', 'C', 'D', 'D_RT', 'X', 'Y']
This does it
list1 = ["A","V","C" ,"D","X","Y","V_RT","D_RT"]
dict1={}
for x in list1:
dict1[x[0]]=x
list2=[]
for key,value in dict1.items():
list2.append(key)
if key!=value:
list2.append(value)
print(list2)
I have a list that looks like this:
json_file_list = ['349148424_20180312071059_20190402142033.json','349148424_20180312071059_20190405142033.json','360758678_20180529121334_20190402142033.json']
and a empty list:
list2 = []
What I want to do is compare the characters up until the second underscore '_', and if they are the same I only want to append the max of the full string, to the new list. In the case above, the first 2 entries are duplicates (until second underscore) so I want to base the max off the numbers after the second underscore. So the final list2 would have only 2 entries and not 3
I tried this:
for row in json_file_list:
if row[:24] == row[:24]:
list2.append(max(row))
else:
list2.append(row)
but that is just returning:
['s', 's', 's']
Final output should be:
['349148424_20180312071059_20190405142033.json','360758678_20180529121334_20190402142033.json']
Any ideas? I also realize this code is brittle with the way I am slicing it (what happens if the string gets longer/shorter) so I need to come up with a better way to do that. Maybe base if off the second underscore instead. The strings will always end with '.json'
I'd use a dictionary to do this:
from collections import defaultdict
d = defaultdict(list)
for x in json_file_list:
d[tuple(x.split("_")[:2])].append(x)
new_list = [max(x) for x in d.values()]
new_list
Output:
['349148424_20180312071059_20190405142033.json',
'360758678_20180529121334_20190402142033.json']
The if statement in this snippet:
for row in json_file_list:
if row[:24] == row[:24]:
list2.append(max(row))
else:
list2.append(row)
always resolves to True. Think about it, how could row[:24] be different from itself? Given that it's resolving to True, it's adding the farthest letter in the alphabet (and in your string), s in this case, to list2. That's why you're getting an output of ['s', 's', 's'].
Maybe I'm understanding your request incorrectly, but couldn't you just append all the elements of the row to a list and then remove duplicates?
for row in json_file_list:
for elem in row:
list2.append(elem)
list2 = sorted(list(set(list2)))
I suppose you can splice what you want to compare, and use the built in 'set', to perform your difference:
set([x[:24] for x in json_file_list])
set(['360758678_20180529121334', '349148424_20180312071059'])
It would be a simple matter of joining the remaining text later on
list2=[]
for unique in set([x[:24] for x in json_file_list]):
list2.append(unique + json_file_list[0][24:])
list2
['360758678_20180529121334_20190402142033.json',
'349148424_20180312071059_20190402142033.json']
list1=['f','l','a','m','e','s'] #This is the predefined list
list2=['e','e','f','a','s','a'] #This is the list with repitition
x=list(set(list2)) # I want to remove duplicates
print(x)
Here I want the variable x to retain the order which list1 has. For example, if at one instance set(list2) produces the output as ['e','f','a','s'], I want it to produce ['f','a','e','s'] (Just by following the order of list1).
Can anyone help me with this?
Construct a dictionary that maps characters to their position in list1. Use its get method as the sort-key.
>>> dict1 = dict(zip(list1, range(len(list1))))
>>> sorted(set(list2), key=dict1.get)
['f', 'a', 'e', 's']
This is one way using dictionary:
list1=['f','l','a','m','e','s'] #This is the predefined list
list2=['e','e','f','a','s','a'] #This is the list with repitition
x=list(set(list2)) # I want to remove duplicates
d = {key:value for value, key in enumerate(list1)}
x.sort(key=d.get)
print(x)
# ['f', 'a', 'e', 's']
Method index from the list class can do the job:
sorted(set(list2), key=list1.index)
What is best usually depends on actual use. With this problem it is important to know the expected sizes of the lists to choose the most efficient approach. If we are keeping much of the dictionary the following query works well and has the additional benefit that it is easy to read.
set2 = set(list2)
x = [i for i in list1 if i in set2]
It would also work without turning list2 into a set first. However, this would run much slower with a large list2.
I am trying to get the first element in a nested list and sum up the values.
eg.
nested_list = [[1, 'a'], [2, 'b'], [3, 'c'], [4, 'd']]
print sum(i[0] for i in nested_list)
However, there are times in which the first element in the lists None instead
nested_list = [[1, 'a'], [None, 'b'], [3, 'c'], [4, 'd']]
new = []
for nest in nested_list:
if not nest[0]:
pass
else:
new.append(nest[0])
print sum(nest)
Wondering what is the better way that I can code this?
Just filter then, in this case testing for values that are not None:
sum(i[0] for i in nested_list if i[0] is not None)
A generator expression (and list, dict and set comprehensions) takes any number of nested for loops and if statements. The above is the equivalent of:
for i in nested_list:
if i[0] is not None:
i[0] # used to sum()
Note how this mirrors your own code; rather than use if not ...: pass and else, I inverted the test to only allow for values you actually can sum. Just add more for loops or if statements in the same left-to-right to nest order if you need more loops with filters, or use and or or to string together multiple tests in a single if filter.
In your specific case, just testing for if i[0] would also suffice; this would filter out None and 0, but the latter value would not make a difference to the sum anyway:
sum(i[0] for i in nested_list if i[0])
You already approached this in your own if test in the loop code.
First of all, Python has no null, the equivalent of null in languages like Java, C#, JavaScript, etc. is None.
Secondly, we can use a filter in the generator expression. The most generic is probably to check with numbers:
from numbers import Number
print sum(i[0] for i in nested_list if isinstance(i[0], Number))
Number will usually make sure that we accept ints, longs, floats, complexes, etc. So we do not have to keep track of all objects in the Python world that are numerical ourselves.
Since it is also possible that the list contains empty sublists, we can also check for that:
from numbers import Number
print sum(i[0] for i in nested_list if i and isinstance(i[0], Number))