Culling certain numbers from a List - python

I have a series of variable lists inside a list, and I'm comparing it to another list. I want, run through each list in aList, analyze each number and as soon its a match in bList, append that number to finalList. I want to return the first match in other words and ignore future matches. For Example:
aList = [[0,1],[8,9,4,5],[7,6,3,2]]
bList = [0,5,1,4]
finalList = [0,4]

Use a for loop with a break.
finalList = []
for sl in aList:
for item in sl:
if item in bList:
finalList.append(item)
break
To iterate with a single for loop you could use the itertools module

Related

Common items in list of lists

I have a list of lists, and I want to make a function that checks if each of the lists inside have exactly one item in common with all the other lists, if so return True.
Couldn't make it work, is there a simple way to do it without using modules?
I've tried something like this:
list_of_lists = [['d','b','s'],['e','b','f'],['s','f','l'],['b','l','t']]
new_list = []
for i in list_of_lists:
for item in i:
new_list.append(item)
if len(set(new_list)) == len(new_list)-len(list_of_lists):
return True
if you want to intersect all the items in the sublist you can convert them to a set and find intersection check if its an empty set.
list_of_lists = [['d','b','s'],['e','b','f'],['s','f','l'],['b','l','t']]
common_items = set.intersection(*[set(_) for _ in list_of_lists])
if len(common_items) == 1:
return True
return False
Using list comprehension:
def func(list_of_lists):
return sum([all([item in lst for lst in list_of_lists[1:]]) for item in list_of_lists[0]]) == 1
Works if each is guaranteed for one of each item. Also if its not, returns True only if there is one match.
use the Counter after joining a list and a compare list to determine occurrences. Ensure at least one item in the resulting list has a frequency of 2.
from collections import Counter
list_of_lists = [['d','b','s'],['e','b','f'],['s','f','l'],['b','l','t']]
for i in range(len(list_of_lists)):
for j in range(i+1,len(list_of_lists)):
result=(list_of_lists[i]+list_of_lists[j])
counts=(Counter(result))
matches={x for k,x in counts.items() if x==2}
if len(matches)==0:
print("missing a match")

Can you use AND in List comprehension conditional statements?

I am trying to use List Comprehension to perform the following. I want to make a new list (unique) that only has the common numbers from both lists.
unique = []
for listcomp in range(len(list1)):
if list1[listcomp] in list2 and list1[listcomp] not in unique:
unique.append(list1[listcomp])
else:
continue
Above works fine but when I create the List comprehension below I get duplicates if list1 has duplicate numbers. i.e. list1 = [1, 1, 2], list2 = [1, 5]. I created my list comprehension as
unique = [list1[listcomp] for listcomp in range(len(list1)) if list1[listcomp] in list2 and list1[listcomp] not in unique]
If I'm getting duplicates I assume the "and" statement isn't being applied? I have read other queries about moving the if statement further up the comprehension statement but this didn't work. Can you use AND to extend your conditions?
Many thanks
My full code is:-
import random as rnd
# Randomly generate the size of your list
list1size = rnd.randint(1,20)
list2size = rnd.randint(1,20)
# Declare your list variables
list1 = []
list2 = []
# Fill your lists with randomly generated numbers upto the listsize generated above
for x in range(list1size):
list1.append(rnd.randint(1,15))
for y in range(list2size):
list2.append(rnd.randint(1,15))
# Not required but easier to read lists once sorted
list1.sort()
list2.sort()
print(list1)
print(list2)
# Now to compare old school
unique = []
# for listcomp in range(len(list1)):
# if list1[listcomp] in list2 and list1[listcomp] not in unique:
# unique.append(list1[listcomp])
# else:
# continue
# Now to compare with list comprehension
unique = [list1[listcomp] for listcomp in range(len(list1)) if list1[listcomp] in list2 and list1[listcomp] not in unique]
# Above doesn't stop duplicates if they are in List1 so I assume you can't use AND
print(f"The common numbers in both lists are {unique}")
You can't access elements produced by a list comprehension as you go along. Your condition list1[listcomp] not in unique will always return True since at that moment in time unique is defined as the empty list intialised in unique = [].
So the and statement is being applied, but not the in way you want.
Instead, you can create a "seen" set holding items you have already found and omit them. The standard implementation is found in the itertools unique_everseen recipe.
If you have the 3rd party toolz library, you can use the identical toolz.unique and feed a generator expression. More Pythonic, you can iterate elements directly rather than using indices:
from toolz import unique
unique = list(unique(i for i in list1 if i in list2))

Python: trying to get three elements of a list with slice over a iterator

I'm new to python.
I'm trying to create another list from a big one just with 3 elements of that list at a time.
I'm trying this:
my_list = ['test1,test2,test3','test4,test5,test6','test7,test8,test9','test10,test11,test12']
new_three = []
for i in my_list:
item = my_list[int(i):3]
new_three.append(item)
# here I'll write a file with these 3 elements. Next iteration I will write the next three ones, and so on...
I'm getting this error:
item = my_list[int(i):3]
ValueError: invalid literal for int() with base 10: 'test1,test2,test3'
I also tried:
from itertools import islice
for i in my_list:
new_three.append(islice(my_list,int(i),3))
Got the same error. I cannot figure out what I'm doing wrong.
EDIT:
After many tries with help here, I could make it.
listrange = []
for i in range(len(li)/3 + 1):
item = li[i*3:(i*3)+3]
listrange.append(item)
Is this what you meant?
my_list = ['test1,test2,test3','test4,test5,test6','test7,test8,test9','test10,test11,test12']
for item in my_list:
print "this is one item from the list :", item
list_of_things = item.split(',')
print "make a list with split on comma:", list_of_things
# you can write list_of_things to disk here
print "--------------------------------"
In response to comments, if you want to generate a whole new list with the comma separated strings transformed into sublists, that is a list comprehension:
new_list = [item.split(',') for item in my_list]
And to split it up into groups of three items from the original list, see the answer linked in comments by PM 2Ring, What is the most "pythonic" way to iterate over a list in chunks?
I have adapted that to your specific case here:
my_list = ['test1,test2,test3','test4,test5,test6','test7,test8,test9','test10,test11,test12']
for i in xrange(0, len(my_list), 3):
# get the next three items from my_list
my_list_segment = my_list[i:i+3]
# here is an example of making a new list with those three
new_list = [item.split(',') for item in my_list]
print "three items from original list, with string split into sublist"
print my_list_segment
print "-------------------------------------------------------------"
# here is a more practical use of the three items, if you are writing separate files for each three
filename_this_segment = 'temp' # make up a filename, possibly using i/3+1 in the name
with open(filename_this_segment, 'w') as f:
for item in my_list_segment:
list_of_things = item.split(',')
for thing in list_of_things:
# obviously you'll want to format the file somehow, but that's beyond the scope of this question
f.write(thing)

how to extract from list python, element with index multiple of 2

I just want to get those with the index that is a multiple of two
code=[1,2,4,7,2,6,8]
ncode=[code[i] for i%2==0]
Just use this indexing method:
code[::2]
If you want the odd index
code[1::2]
Generally, this is how it works:
seq = L[start:stop:step]
seq = L[::2] # get every other item, starting with the first
seq = L[1::2] # get every other item, starting with the second
You can use list comprehensions this way :
code=[1,2,4,7,2,6,8]
print [val for i,val in enumerate(code) if i%2==0]
enumerate() returns the index and value at the index, which is stored in i and value respectively.
For more details:
list comprehension
enumerate
code = [1,2,4,7,2,6,8]
new_code = []
for i in range(0, len(code), 2): ### iterate over even indexes
new_code.append(code[i])
print new_code

Making a new list in alphabetical order

My python instructions are: Write a function called merge
takes two lists of strings that are each in alphabetical order.
The function should return a list that has all the strings
in alphabetical order.
The function should return a list that has all the strings in alphabetical
order.
For example, if the function were given the two lists
[“cat”, “dog”, “pat”] and [ “bat”, “hamster”, “piglet”, “worm”]
it should return the list
[“bat”, “cat”, “dog “, hamster”, “pat”, “piglet”, “worm”].
Roughly speaking you will start with an empty list to hold the merged list
and an index set to 0 at the beginning of each list.
Compare the first words. Whichever comes first in alphabetical
order gets appended to the merged list and the index of that list
is increased. Continue until one of the lists is empty and copy
the remainder of the other list to the merged list.
Right now I have the code
list1 = ["cat", "dog", "pat"]
list2 = [ "bat", "hamster", "piglet", "worm"]
def merge (list1, list2):
newlist = []
newlist = list1 +list2
final = sorted(newlist)
return final
print merge (list1, list2)
It works, but it's not following instructions. I'm not really sure how to do it with comparing the two lists then appending them to the new list. I also didn't do it with an index set to 0. Can anyone help tweak my code so it fits the instructions?
lets start by writing a compare function
def cmp_lists(L1,L2):
'''returns the first item of the lesser list and the remaining lists'''
if L1 < L2:
return L1[0],(L1[1:],L2)
return L2[0],(L1,L2[1:])
now write a method to merge 2 lists
def merge(L1,L2):
if not L1: #if L1 is empty return L2
return L2
elif not L2: #if L2 is empty return L1
return L1
#otherwise take the first item from one of the lists
next_itm,(L1,L2) = cmp_lists(L1,L2)
# and recursively carry on
return [next_itm] + merge(L1,L2)
What you have been instructed is to write an implementation for a simple merge function that is popularly used in merge-sort sorting algorithm.
Since both lists are already sorted, you don't need to join and sort them again. Rather, just loop until one of the lists is empty and keep comparing the first elements of both lists. Pop the shorter element and add to the newer list.
Keep doing so until one or both of the lists become empty. If one of the lists have extra elements remaining, add all of them to the new list.
I encourage you to write the code once again.
It's a merge sort? Oh that's not tough. Just reverse both lists, compare each pair, and pop the loser. Once either list is empty, the remaining list is sorted in ascending order compared to the entire result, so just concatenate it.
from operator import itemgetter as iget
def merge(lst1, lst2):
lst1, lst2 = lst1[::-1], lst2[::-1]
# popping from the end is MASSIVELY better than popping from the front
result = []
while True:
if not all([lst1, lst2]): # one list is empty:
return result + lst1[::-1] + lst2[::-1] # so add them both and return
lst_to_pop_from = min(lst1,lst2, key=iget(-1))
# gets the list with the smallest final element
result.append(lst_to_pop_from.pop())
# DEMO
In [53]: list1 = ["cat", "dog", "pat"]
In [54]: list2 = [ "bat", "hamster", "piglet", "worm"]
In [55]: merge(list1, list2)
Out[55]: ['bat', 'cat', 'dog', 'hamster', 'pat', 'piglet', 'worm']
Merge sort works by looking at the top elements of the list and putting them in the newly created list.
def merge(list1, list2): # assume input lists are sorted
iter1 = iter(list1) # iterator on the list
iter2 = iter(list2)
top1 = iter1.next() # first element of the list
top2 = iter2.next()
newlist = [] # new list to fill in
while True: # loop will exit with break statement
if top1 <= top2:
newlist.append(top1) # put smaller element in new list
try:
top1 = iter1.next() # try to get next element in list1
except StopIteration:
newlist.append(top2) # if not, fill list with top2
newlist.extend(list(iter2)) # and rest of list2
break # and exit loop
else:
newlist.append(top2)
try:
top2 = iter2.next()
except StopIteration:
newlist.append(top1) # if not, fill list with top1
newlist.extend(list(iter1)) # and rest of list1
break
return newlist

Categories

Resources