Referencing value and values after it - python

Let's say I have a list:
list1 = [1,2,3,4,5,6,7,8,9,10]
I want a loop that will, for every value, check if a concatenated version of it and any other beyond it are the same as an existing value in another list. Make sense? No? Here's what I want to come out.
The lists
list1 = ['3','ex','fish nets','orange','banana','exampl','apple']
list2 = ['e','x','blah','exam','p','l','blahblah']
Finally, we take these lists and let's say I want every time a value and any adjacent number of values after it are equivalent to a value in list1 for them to concatenate. (i.e. values e and x concatenate to be ex which exists in list1.) So, it modifies list2 to be:
list2 = ['ex','blah','exam','p','l','blahblah']
The same would be for three or four or however many values are in the list. The loop would reexamine the rest of possible combinations (only left -> right) and do the same. exam, p, and l concatenate to the value in list1 exampl. list2 then becomes:
list2 = ['ex','blah','exampl','blahblah']
The wording on this is pretty poor but I hope the examples were in-depth enough to give a representation of what I need.

list1 = ['3','ex','fish nets','orange','banana','exampl','apple']
list2 = ['e','x','blah','exam','p','l','blahblah']
a=list2
j=['e','x','blah','exam','p','l','blahblah']
t=[]
for y in range(0, len(j)):
for i in range(1,len(j)-y):
r=''
t=j[y:y+i+1] #Create a list of adjacent elements.
for x in t:
r+=str(x) #make it string and check if it fits.
if r in list1:
list2[y]=r
for e in range(y+1,y+i+1):
list2[e]=0 # to avoid a mess with indexes.
while 0 in list2:
list2.remove(0)
print list2
I know it's very clumpsy, but it seems to work.

Related

Compare list1 objects against the entire list2 objects for the output of non-intersecting CIDRs using python ipaddr library

# GOAL: Compare list1 objects against the entire list2 objects for the output of non-intersecting CIDRs and output CIDRs that do NOT intersect
#
# example: item #1 in list1 gets checked against all entries in list2 for non-intersecting CIDRs
# then item #2 in list1 gets checked against all entries in list2 for non-intersecting CIDRs
# then item #3 in list1 gets checked against all entries in list2 for non-intersecting CIDRs
# output any in CIDRs in list1 that do NOT intersect any item in any CIDR from list2
# list1 and list2 are literally 2 files of which both contain tons of IPs with their CIDR range
# Need to check for any list1 items intersecting IPs with any of list 2 items
# Servers as loop counters and the lines contained in list1
list1_counter = 0
# Servers as loop counters and the lines contained in list2
list2_counter = 0
# collect results from CIDR check
results = []
# loop until at the line count of line2 as it reached the end of list
while list1_counter <= list2_cidr_count:
# for list1's first line compared to all of list2 lines
for list1_lines[list1_counter] in list2_lines:
print(list1_lines[list1_counter])
print(list2_lines[list2_counter])
# Compare CIDR for any intersections for list1's first line to all of list2 lines
a = (ipaddr.IPNetwork(list1_lines[list1_counter]).overlaps(list2_lines[list2_counter]))
# append to results list here
results.append(a)
# increase counter to go to list1's second line and start from top
list2_counter += 1
New to python and lost in logic. Does anyone have an example I can use or just knows how to iterate this with the counters the correct way? I'm almost thinking I need a nested statement to work but it fails in many different ways each time I try.
Appreciate any insight I can get!
What helped me when I was starting out writing code, creating loops and flow-control was writing down what I wanted to do in basic English before beginning to code.
So, if we simplify the instructions in your code, and skip the part about CIDRs, then we can write it down as the following:
We have two lists:
list1
list2
For each value inside of list1, we want to go over each value inside of list2 and compare them to each other.
If the current value of list1 is found inside of list2, then we want to discard that value. However, if no matches were found, then we want to save that value.
Okay, so now we can create a simpler example with the above statements as the scaffold of our loops and comparisons:
list1 = [0,1,2,3,4,5,6,7,8,9]
list2 = [1,3,5,7,9]
# A variable that holds all values we want to save.
saved_values = []
# loop over each value of list1
for value in list1:
not_in_list2 = True
# For every value inside of list1,
# we go over list2's values, one by one in a loop
for other_value in list2:
# if the comparison is true,
# then we set the variable "not_in_list2" to False
if value == other_value:
not_in_list2 = False
# If all of the comparisons inside of the list2-loop
# was False then the variable never changed,
# and we can add the variable to our saved_values list.
if not_in_list2:
saved_values.append(value)
# Finally, we print out the saved_values variable
print(saved_values)
Output:
[0, 2, 4, 6, 8]
You should now have the building blocks to finish your program.

How to sort the list values according to the first letter of the value in Python

I have a issue in lists. I have a list =['randomf','decisiont','extremeg'] which is appended with another list list2 = ['bike','age','car'], and then sorted according it together which means each value of first list have the appended values of list2(e.g:'randomf_bike','randomf_age' ,'randomf_car') but when I sort it turns to be like this(e.g: 'randomf_age','randomf_bike' ,'randomf_car') Its not only sorting according to the first letter of the value but also sorting according to the letter after '_'. How can I sort according to the first letter?
My code:
list =['randomf','decisiont','extremeg']
list2 = ['bike','age','car']
new_list = [el1+'_'+el2 for el2 in list2 for el1 in sorted(set(list))]
new_list = sorted(new_list)
which gives : new_list = ['decisiont_age','decisiont_bike' ,'decisiont_car','extremeg_age','extremeg_bike' ,'extremeg_car','randomf_age','randomf_bike' ,'randomf_car']
The excepted output is:
new_list = ['decisiont_bike','decisiont_age' ,'decisiont_car','extremeg_bike','extremeg_age' ,'extremeg_car', 'randomf_bike','randomf_age' ,'randomf_car']
You can give a key function to the call to sorted. If you want to sort only on the part of the string before the first _ character, you can do sorted(new_list, key=lambda s: s.split('_', 1)[0]).
But you might also be able to avoid that second sort, if you assemble your compound strings in the right order from the start. I think you can just change the order of your two-level iteration and it should match what you want (you're already sorting the first list):
new_list = [el1+'_'+el2 for el1 in sorted(set(list)) for el2 in list2] # change order here
# don't sort again!

Check number not a sum of 2 ints on a list

Given a list of integers, I want to check a second list and remove from the first only those which can not be made from the sum of two numbers from the second. So given a = [3,19,20] and b = [1,2,17], I'd want [3,19].
Seems like a a cinch with two nested loops - except that I've gotten stuck with break and continue commands.
Here's what I have:
def myFunction(list_a, list_b):
for i in list_a:
for a in list_b:
for b in list_b:
if a + b == i:
break
else:
continue
break
else:
continue
list_a.remove(i)
return list_a
I know what I need to do, just the syntax seems unnecessarily confusing. Can someone show me an easier way? TIA!
You can do like this,
In [13]: from itertools import combinations
In [15]: [item for item in a if item in [sum(i) for i in combinations(b,2)]]
Out[15]: [3, 19]
combinations will give all possible combinations in b and get the list of sum. And just check the value is present in a
Edit
If you don't want to use the itertools wrote a function for it. Like this,
def comb(s):
for i, v1 in enumerate(s):
for j in range(i+1, len(s)):
yield [v1, s[j]]
result = [item for item in a if item in [sum(i) for i in comb(b)]]
Comments on code:
It's very dangerous to delete elements from a list while iterating over it. Perhaps you could append items you want to keep to a new list, and return that.
Your current algorithm is O(nm^2), where n is the size of list_a, and m is the size of list_b. This is pretty inefficient, but a good start to the problem.
Thee's also a lot of unnecessary continue and break statements, which can lead to complicated code that is hard to debug.
You also put everything into one function. If you split up each task into different functions, such as dedicating one function to finding pairs, and one for checking each item in list_a against list_b. This is a way of splitting problems into smaller problems, and using them to solve the bigger problem.
Overall I think your function is doing too much, and the logic could be condensed into much simpler code by breaking down the problem.
Another approach:
Since I found this task interesting, I decided to try it myself. My outlined approach is illustrated below.
1. You can first check if a list has a pair of a given sum in O(n) time using hashing:
def check_pairs(lst, sums):
lookup = set()
for x in lst:
current = sums - x
if current in lookup:
return True
lookup.add(x)
return False
2. Then you could use this function to check if any any pair in list_b is equal to the sum of numbers iterated in list_a:
def remove_first_sum(list_a, list_b):
new_list_a = []
for x in list_a:
check = check_pairs(list_b, x)
if check:
new_list_a.append(x)
return new_list_a
Which keeps numbers in list_a that contribute to a sum of two numbers in list_b.
3. The above can also be written with a list comprehension:
def remove_first_sum(list_a, list_b):
return [x for x in list_a if check_pairs(list_b, x)]
Both of which works as follows:
>>> remove_first_sum([3,19,20], [1,2,17])
[3, 19]
>>> remove_first_sum([3,19,20,18], [1,2,17])
[3, 19, 18]
>>> remove_first_sum([1,2,5,6],[2,3,4])
[5, 6]
Note: Overall the algorithm above is O(n) time complexity, which doesn't require anything too complicated. However, this also leads to O(n) extra auxiliary space, because a set is kept to record what items have been seen.
You can do it by first creating all possible sum combinations, then filtering out elements which don't belong to that combination list
Define the input lists
>>> a = [3,19,20]
>>> b = [1,2,17]
Next we will define all possible combinations of sum of two elements
>>> y = [i+j for k,j in enumerate(b) for i in b[k+1:]]
Next we will apply a function to every element of list a and check if it is present in above calculated list. map function can be use with an if/else clause. map will yield None in case of else clause is successful. To cater for this we can filter the list to remove None values
>>> list(filter(None, map(lambda x: x if x in y else None,a)))
The above operation will output:
>>> [3,19]
You can also write a one-line by combining all these lines into one, but I don't recommend this.
you can try something like that:
a = [3,19,20]
b= [1,2,17,5]
n_m_s=[]
data=[n_m_s.append(i+j) for i in b for j in b if i+j in a]
print(set(n_m_s))
print("after remove")
final_data=[]
for j,i in enumerate(a):
if i not in n_m_s:
final_data.append(i)
print(final_data)
output:
{19, 3}
after remove
[20]

Removing non-matching items from datasets

I have two datasets consisting of lists of nested lists such that each item in the list looks like list1[i]= [a, x, y b] and list2[j] = [c, x, y, d] and where the length of the two lists does not necessarily match. I'd like to be able to go through the lists, preserve their order, and eliminate any of the sub-lists that do not contain matching x values. In the end, I want to get two lists of identical length and where for each index, the x value is the same in corresponding sub lists.
Right now I have a somewhat messy code that assumes that the set of x values in list2 is a subset of those in list1 (true at the moment) and then proceeds to remove items where the x values don't match.
len_diff = len(list1) - len(list2)
if len_diff > 0:
removed = []
for (counter, row) in enumerate(list2):
while list1[counter][1] != list2[counter][1]:
removed.append(list1.pop(counter))
new_len_diff = len(list1) - len(list2)
if new_len_diff < 0:
raise IndexError('Data sets do not completely overlap')
else:
for i in range(new_len_diff):
removed.append(temp_data.pop())
So basically I'm removing any items that don't x values match until they start matching again and then removing the end of list1 beyond the x values in list2 (raising an exception if I've cut too much out of list1).
Is there a better way to do this?
I don't necessarily need to relax the assumption that all x values in list2 are in list1 at the moment but it would make this code more useful to me in the future for other data manipulations. The biggest hole in my code now is that if there is a gap in my list1 data, I'll remove my entire list.
You should try this:
list1 = list2 = [x for x in list1 if x[1] in zip(*list2)[1]]
EDIT
Based on the comments below, the OP adapted this answer to do what was wanted by doing
list1 = [x for x in list1 if x[1] in zip(*list2)[1]]
list2 = [x for x in list2 if x[1] in zip(*list1)[1]]

Indices are not synchronous of using one lists indices in another

Coming from R, this was hard to grasp. Taking elements from a list start with position 0.
The problem is that using one list to select items from another list are not running at the same pace here.
list1 = [1,2,3,4]
list2 = [1,2,3,4]
for x in range(0, len(list1)):
print(list1[list2[x]])
This will result in:
>> 2
>> 3
>> 4
>> IndexError: list index out of range
When I put an extra item in the start of list1, and added an item at the end of list2, the problem stops (simply because they are not synchronous like this).
Obviously I am not familiar with the language yet, what would be the correct way to use values from one list to select values from another?
Is this the correct way to think of it?
for x in range(0, len(list1)):
print(list1[list2[x]-1])
Python is 0-index based. seq[0] is the first element in seq.
R is 1-index based.
So, yes, in python you could use
list1 = [1,2,3,4]
list2 = [1,2,3,4]
for x in range(0, len(list2)):
print(list1[list2[x]-1])
The range should go up to len(list2), not len(list1).
Also, range(0, len(list2)) is the same as range(len(list2)). When
range is passed only one argument, it is interpreted as the stop
value, with a start value of 0 taken by default.
Note that in Python
for x in range(...):
can often be avoided, and if so, is preferable. Instead, you can write
for item in list2:
print(list1[item-1])
and item will be assigned to each of the items in list2.
If your list has 4 items, your indexes must run from 0 to 3, so using the value 4 throws an error. Here's an example with letters which might make it clearer:
list1 = [0,2,1,3]
list2 = ['a','a','d','m']
for x in list1:
print(list2[x]),
=> a d a m

Categories