Find unique numbers that occur in two different lists - python

I have this code:
list1 = input()
list2 = input()
unique = list(set(list1).intersection(list2))
print(len(unique))
and I want to find the unique numbers that occur in both lists.
However, when I enter the lists [1,2,3,4,5,6] and [6,5,4,3,2,1] it returns 7, instead of 6.
When I edit my code to:
list1 = [1,2,3,4,5,6]
list2 = [6,5,4,3,2,1]
unique = list(set(list1).intersection(list2))
print(len(unique))
It outputs 6 correctly. What is going on in my user input code?

Because the inputs are cast to string when using input, and by constructing a set you're getting:
list1 = '1,2,3,4,5,6'
print(set(list1))
# {',', '1', '2', '3', '4', '5', '6'}
list2 = '6,5,4,3,2,1'
set(list2)
# {',', '1', '2', '3', '4', '5', '6'}
The commas are included, resulting in:
list(set(list1).intersection(list2))
# [',', '1', '6', '5', '3', '4', '2']

You are not converting your second input to a set.
I'd write it at as the follows:
set1 = set(input())
set2 = set(input())
unique = list(set1.intersection(set2))
print(len(unique))

input returns a string, and you have to cast or better parse it first.
One option is json, e.g.
import json
def parse():
return json.loads(input())
list1 = parse() #"[1,2,3,4,5,6]" parsed to [1,2,3,4,5,6]
list2 = parse() #"[6,5,4,3,2,1]" parsed to [6,5,4,3,2,1]
unique = list(set(list1).intersection(set(list2)))
print(len(unique))
Obviously you could use eval(input(), but that could not be considered safe, as it allows executing arbitrary code. Another possible parsing function that does not require brackets could be
def parse():
ip = input()
return [int(element) for element in ip.split(',')]
list1 = parse() #"1,2,3,4,5,6" parsed to [1,2,3,4,5,6]

Related

Split array based on value

I have an array:
foo = ['1', '2', '', '1', '2', '3', '', '1', '', '2']
¿Is there any efficient way to split this array into sub-arrays using '' as separator?
I want to get:
foo = [['1', '2'], ['1', '2', '3'], ['1'], ['2']]
In one line:
[list(g) for k, g in itertools.groupby(foo, lambda x: x == '') if not k]
Edit:
From the oficial documentation:
groupby
generates a break or new group every time the value of the key
function changes (which is why it is usually necessary to have sorted
the data using the same key function).
The key I generate can be True, or False. It changes each time we find the empty string element. So when it's True, g will contain an iterable with all the element before finding an empty string. So I convert this iterable as a list, and of course I add the group only when the key change
Don't know how to explain it better, sorry :/ Hope it helped
Create a list containing a single list.
output = [[]]
Now, iterate over your input list. If the item is not '', append it to the last element of output. If it is, add an empty list to output.
for item in foo:
if item == '':
output.append([])
else:
output[-1].append(item)
At the end of this, you have your desired output
[['1', '2'], ['1', '2', '3'], ['1'], ['2']]

Convert a number to an array of digits using a one line for loop in Python

I am trying t convert a number as follows:
input -> 123456
output -> ['1','2','3','4','5','6']
The following loop does work:
number = 123456
defg = []
abc = str(number)
for i in range(len(abc)):
defg.append(abc[i])
However, when i try this in the form of a one line for loop, the output is ['None','None','None','None']
My one line loop is as follows:
number = 123456
defg = []
abc = str(number)
defg= [[].append(abc[i]) for i in range(len(abc))]
Any idea what I am doing wrong?
The answers above are concise, but I personally prefer vanilla list comprehension over map, as powerful as it is. I add this answer simply for the sake of adding diversity to the mix, showing that the same can be achieved without using map.
str_list = [abc[i] for i in range(len(abc))]
We can strive for a more Pythonic solution by avoiding direct indexing and using a simpler loop.
better_str_list = [char for char in abc]
This list comprehension is basically just a translation of the for loop you already have.
Try this:
x = 527876324
print(list(str(x))
Output
['5', '2', '7', '8', '7', '6', '3', '2', '4']
here the solution
list(map(lambda x: str(x), str(number)))
Out[13]: ['1', '2', '3', '4', '5', '6']
or you can do this
list(map(str, str(number)))
Out[13]: ['1', '2', '3', '4', '5', '6']
or this
list(str(number))
['1', '2', '3', '4', '5', '6']
duplicate you can see more here
Splitting integer in Python?
Solution
As your expection the result is
number = 123456
defg = []
abc = str(number)
[defg.append(abc[i]) for i in range(len(abc))]
print(defg)
When you run the loop the values are append to defg but it return none. you assign the None value to defg so it will show the None output
Recomanded way
You can use list metnod to convert the number to list
number = 865393410
result = list(str(number))
print(result)
If you want int in list try this
number = 865393410
result = []
for i in list(str(number)):
result.append(int(i))
print(result)
With single line loop
number = 865393410
result = []
[result.append(int(i)) for i in list(str(number))]
print(result)
The last one is recommended for you

Python: Inserting into a list using length as index

All,
I've recently picked up Python and currently in the process of dealing with lists. I'm using a test file containing several lines of characters indented by a tab and then passing this into my python program.
The aim of my python script is to insert each line into a list using the length as the index which means that the list would be automatically sorted. I am considering the most basic case and am not concerned about any complex cases.
My python code below;
newList = []
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
newList.insert(size, data)
for i in range(len(newList)):
print ( newList[i])
My 'test' file below;
2 2 2 2
1
3 2
2 3 3 3 3
3 3 3
My expectation of the output of the python script is to print the contents of the list in the following order sorted by length;
['1']
['3', '2']
['3', '3', '3']
['2', '2', '2', '2']
['2', '3', '3', '3', '3']
However, when I pass in my test file to my python script, I get the following;
cat test | ./listSort.py
['2', '2', '2', '2']
['1']
['3', '2']
['3', '3', '3']
['2', '3', '3', '3', '3']
The first line of the output ['2', '2', '2', '2'] is incorrect. I'm trying to figure out why it isn't being printed at the 4th line (because of length 4 which would mean that it would have been inserted into the 4th index of the list). Could someone please provide some insight into why this is? My understanding is that I am inserting each 'data' into the list using 'size' as the index which means when I print out the contents of the list, they would be printed in sorted order.
Thanks in advance!
Inserting into lists work quite differently than what you think:
>>> newList = []
>>> newList.insert(4, 4)
>>> newList
[4]
>>> newList.insert(1, 1)
>>> newList
[4, 1]
>>> newList.insert(2, 2)
>>> newList
[4, 1, 2]
>>> newList.insert(5, 5)
>>> newList
[4, 1, 2, 5]
>>> newList.insert(3, 3)
>>> newList
[4, 1, 2, 3, 5]
>>> newList.insert(0, 0)
>>> newList
[0, 4, 1, 2, 3, 5]
Hopefully you can see two things from this example:
The list indices are 0-based. That is to say, the first entry has index 0, the second has index 1, etc.
list.insert(idx, val) inserts things into the position which currently has index idx, and bumps everything after that down a position. If idx is larger than the current length of the list, the new item is silently added in the last position.
There are several ways to implement the functionality you want:
If you can predict the number of lines, you can allocate the list beforehand, and simply assign to the elements of the list instead of inserting:
newList = [None] * 5
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
newList[size - 1] = data
for i in range(len(newList)):
print ( newList[i])
If you can predict a reasonable upper bound of the number of lines, you can also do this, but you need to have some way to remove the None entries afterwards.
Use a dictionary:
newList = {}
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
newList[size - 1] = data
for i in range(len(newList)):
print ( newList[i])
Add elements to the list as necessary, which is probably a little bit more involved:
newList = []
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
if len(newList) < size: newList.extend([None] * (size - len(newList)))
newList[size - 1] = data
for i in range(len(newList)):
print ( newList[i])
I believe I've figured out the answer to my question, thanks to mkrieger1. I append to the list and then sort it using the length as the key;
newList = []
for line in sys.stdin:
data = line.strip().split('\t')
newList.append(data)
newList.sort(key=len)
for i in range(len(newList)):
print (newList[i])
I got the output I wanted;
/listSort.py < test
['1']
['3', '2']
['3', '3', '3']
['2', '2', '2', '2']
['2', '3', '3', '3', '3']

how to remove the first occurence of an integer in a list

this is my code:
positions = []
for i in lines[2]:
if i not in positions:
positions.append(i)
print (positions)
print (lines[1])
print (lines[2])
the output is:
['1', '2', '3', '4', '5']
['is', 'the', 'time', 'this', 'ends']
['1', '2', '3', '4', '1', '5']
I would want my output of the variable "positions" to be; ['2','3','4','1','5']
so instead of removing the second duplicate from the variable "lines[2]" it should remove the first duplicate.
You can reverse your list, create the positions and then reverse it back as mentioned by #tobias_k in the comment:
lst = ['1', '2', '3', '4', '1', '5']
positions = []
for i in reversed(lst):
if i not in positions:
positions.append(i)
list(reversed(positions))
# ['2', '3', '4', '1', '5']
You'll need to first detect what values are duplicated before you can build positions. Use an itertools.Counter() object to test if a value has been seen more than once:
from itertools import Counter
counts = Counter(lines[2])
positions = []
for i in lines[2]:
counts[i] -= 1
if counts[i] == 0:
# only add if this is the 'last' value
positions.append(i)
This'll work for any number of repetitions of values; only the last value to appear is ever used.
You could also reverse the list, and track what you have already seen with a set, which is faster than testing against the list:
positions = []
seen = set()
for i in reversed(lines[2]):
if i not in seen:
# only add if this is the first time we see the value
positions.append(i)
seen.add(i)
positions = positions[::-1] # reverse the output list
Both approaches require two iterations; the first to create the counts mapping, the second to reverse the output list. Which is faster will depend on the size of lines[2] and the number of duplicates in it, and wether or not you are using Python 3 (where Counter performance was significantly improved).
you can use a dictionary to save the last position of the element and then build a new list with that information
>>> data=['1', '2', '3', '4', '1', '5']
>>> temp={ e:i for i,e in enumerate(data) }
>>> sorted(temp, key=lambda x:temp[x])
['2', '3', '4', '1', '5']
>>>

Reading both numbers in an integer instead of the first when sorting

I'm trying to sort data from a text file and show it in python.
So far i have:
text_file = open ("Class1.txt", "r")
data = text_file.read().splitlines()
namelist, scorelist = [],[]
for li in data:
namelist.append(li.split(":")[0])
scorelist.append(li.split(":")[1])
scorelist.sort()
print (scorelist)
text_file.close()
It sorts the the data, however it only reads the first number:
['0', '0', '10', '3', '3', '5']
It reads 10 as "1"
This is what my text file looks like:
Harry:3
Jarrod:10
Jacob:0
Harold:5
Charlie:3
Jj:0
It's lexographically sorting, if you need integer sorting, append the split as an int
scorelist.append(int(li.split(":")[1]))
Since scorelist is a list of strings, "10" shows up before "3" because the first character in "10" is less than the first character in "3" (lexicographic sorting -- like words in a dictionary). The trick here is to tell python to sort integers. You can do that as the other answers point out by sorting a list of integers rather than a list of strings, OR you could use a key function to sort:
scorelist.sort(key=int)
This tells python to sort the items as integers rather than as strings. The nice thing here is that you don't need to change the data at all. You still end up with a list of strings rather than a list of integers -- you just tell python to change how it compares the strings. Neat.
demo:
>>> scorelist = ['3', '10', '0', '5', '3', '0']
>>> scorelist_int = [int(s) for s in scorelist]
>>>
>>> scorelist.sort(key=int)
>>> scorelist
['0', '0', '3', '3', '5', '10']
>>>
>>> scorelist_int.sort()
>>> scorelist_int
[0, 0, 3, 3, 5, 10]
The data are actually strings. The sort is done like in a dictionary.
You should convert scores into int:
scorelist.append(int(li.split(":")[1]))

Categories