Appending value into list without duplicates - python

I have a list of integers containing:
intlist = [19,4,2,4]
and i want to append the value from the intlist into a list of list such that:
noDuplist = [[19,0],[4,1],[2,2]]
where the first index represents the value from the intlist and the second index represents the index of the value in the intlist. 19 is at index 0, 4 is at index 1 and 2 is at index 2. Since there is another 4 i do not want to include that since i didn't want duplicate hence the last 4 is just going to be left out.
I tried something like:
noDuplist = []
for i in range(len(intlist)):
if intlist[i] not in noDuplist:
noDuplist.append([intlist[i],i])
but I'm still getting
[[19, 0], [4, 1], [2, 2], [4, 3]]
where the [4,3] shouldnt be there. Would appreciate some help on this

I assume you want to retain the indices from the original sequence.
Thus what you want is something that remembers at what index was the value
first seen in the original sequence.
The problem is in your condition since
if intlist[i] not in noDuplist:
# something
would check if 4 was present in [[19, 0], [4, 1], [2, 2]]] which it isn't.
A cleaner way of doing this could be using dictionaries or sets.:
intlist = [19,4,2,4]
seen_so_far, noDuplist = set(), []
for i, v in enumerate(intlist):
if v not in seen_so_far:
noDuplist.append([v, i])
seen_so_far.add(v)
print(noDuplist)
Which gives the output [[19, 0], [4, 1], [2, 2]]

The first thing I'd suggest is not bothering storing the index as well as the value. You'll know the index when extracting elements anyway.
The first approach that comes to my mind (not sure if it's optimal) involves using a dictionary in combination with your list. Whenever you try to insert a value, check if it exists in your dictionary. If it doesn't, add it to the dictionary and your list. If it does, don't add it.
This would result in O(N) complexity.
Edit:
I didn't read your description thoroughly enough. Since you need the index from the original array, simply enter both as a key/value pair into your dictionary instead.

Related

Fastest way to exclude numbers from an array in each loop iteration

I am not a python expert.
I am trying to implement a solution for a K-Coloring interval problem.
Only using the python standard library, so no numpy,.
What i want to achieve :
So i have a sorted list of elements, and in each loop iteration i need to exclude multiple elements , so that in the next iteration the loop Continues to work on the sorted subset that resulted from the last iteration.
In each iteration i am accessing the indexes using binary search algorithm, and the list must always be sorted when worked on.
I've tried using array.pop(index) but my solution was slow and not efficient for a list of 100000 elements since it has O(n) complexity according to https://wiki.python.org/moin/TimeComplexity with n being number of elements in the list.
I've tried storing the inputs in a set() and work on them, however since in every iteration i have to execute binary search algorithm i can't store them because i will be needing to access elements by index for the sake of binary search, which is not possible in a set TypeError: 'set' object is not subscriptable.
Ex:
Input is a list sorted in ascending order according to the second item of each subarray.
arr = [[0, -1, 0], [1, 4, 0], [3, 5, 0], [0, 6, 0], [4, 7, 0], [3, 7, 0], [5, 9, 0], [6, 10, 0]]
for i in range(len(arr)) :
x = binarysearch(arr, value) #returns an index
while x > 0 :
helper = x
array.exclude(x)
x = binarysearch(arr, arr[helper][0]) #returns an index
I don't want all the arr[x] that were excluded from the last iteration to be included in the current one.
Any ideas of thoughts would be much appreciated.
Thanks in advance

Changing second-to-last entry in list changes all preceding entries

The code I'm trying to write includes for loops that fill in a list in reverse order: The last entry is set first, and then the t-th entry is set based on the (t+1)th entry, iterating backwards until it gets to the 0th entry. Unfortunately, I kept the getting the strange problem of all the entries before the 2nd-to-last being equal to the 2nd-to-last.
Strangely enough, I managed to reproduce the problem even without the for loop.
The entries in this example are lists of length 3 because that's how it is in my real work. The problem goes away if I just make the entries ints.
def bet(p):
bet=[[0,0,0]]*p
bet_end=[]
for k in range(0,3):
bet_end.append(1)
bet[p-1]=bet_end
for k in range(0,3):
bet[p-2][k]=2
return bet
test=bet(5)
I expect the output to be
[[0,0,0],[0,0,0],[0,0,0],[2,2,2],[1,1,1]]
Instead, I get
[[2,2,2],[2,2,2],[2,2,2],[2,2,2],[1,1,1]]
Why did the 0th, 1st and 2nd entries get affected by the change to the 3rd entry?
Change this line
bet=[[0,0,0]]*p
to,
bet=[[0,0,0] for i in range(p)]
Output:
>>> bet(5)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [2, 2, 2], [1, 1, 1]]
Why?
Read here to know how to initialize lists properly.

Separating array elements from each other

I'm trying to separate every continuous segment of consecutive numbers in a different array.
For example,
# Input
x=[1,2,3,4,5,8,11,12,13,18]
# Output:
x=[[1,2,3,4,5],[8],[11,12,13],[18]]
The existing code,
x=[1,2,3,4,5,8,11,12,13,18]
temp=[]
firstnumber=0
for i in range(1,len(x)-1,1):
current=x[i]
previous=x[i-1]
if ((current-previous)!=1):
mm=(x[firstnumber:i-1])
temp.append(mm)
firstnumber=x[i]
print(temp)
I only got [[1, 2, 3, 4], []] as a result and I can't figure out why.
I have tried to answer this question changing as little of your code as possible.
x=[1,2,3,4,5,8,11,12,13,18]
temp=[]
firstnumber=0
first_index = 0
for i in range(1, len(x)):
current=x[i]
previous=x[i-1]
if ((current-previous)!=1):
mm = x[first_index:i]
temp.append(mm)
firstnumber = x[i]
first_index = i
temp.append(x[first_index:])
print(temp) # [[1, 2, 3, 4, 5], [8], [11, 12, 13], [18]]
What I changed:
firstnumber is being used as an index, but in reality is an element of the list, so we need to use first_index = i, the current index on that iteration.
The loop did not cover all the elements of the list, we need to go all the way to the end of the list so we iterate over range(1, len(x)
Finally even if the loop completes it will be missing the last sequence unless we add it after the loop, hence the addition of temp.append(x[first_index:])
NOTE: This method will work with the input you have but it not robust for all cases, nor is it the most efficient way to do this, however, your question was why it did not work as is so hopefully this answers that.
My answer does not intend to provide repaired code, but rather doing described task.
Note that you might use -1 index meaning last element. I would do it following way
x=[1,2,3,4,5,8,11,12,13,18]
temp=[x[:1]]
for i in x[1:]:
if temp[-1][-1]+1!=i: temp.append([])
temp[-1].append(i)
print(temp)
Output:
[[1, 2, 3, 4, 5], [8], [11, 12, 13], [18]]
Explanation: I firstly load first element as one-element list, then for following elements, if there is difference other than 1 between current and last-seen element then I append new empty list to temp, then independently from full-filling or not condition I add current element to last sublist.
x=[1,2,3,4,5,8,11,12,13,18]
x.append(x[-1]-2)
temp=[]
firstnumber=0
for i in range(1, len(x)):
current=x[i]
previous=x[i-1]
if ((current-previous)!=1):
mm=(x[firstnumber:i])
temp.append(mm)
firstnumber=i
print(temp)
In the code, the variable firstnumber is, I believe, supposed to contain the index of the first element of any continuous segment of consecutive numbers.
However, when you do firstnumber=x[i] that purpose is lost. Instead you can do, firstnumber = i and then it will work.
Also, this implementation will not append the last consecutive segment. As a result, you will have to do that outside the loop.

Restricting a Change to Only 1 List

I have nested lists (ie. [[list1],[list2]] and I want to make a change to only the first list.
My function is given as below:
function_name(data, list_number, change)
should return a change to only the list_number provided in the data
So my overall question is, how do I restrict this change to only the list_number given? If this is unclear please feel free to ask and clarify.
Ex:
Where the 'change' is already known which index it is going to replace, in this case it's going to replace the 2nd index of the first list (ie. 2)
data = [[1,2,3],[4,5,6]]
function_name(data, 1, 6)
data = [[1,6,3],[4,5,6]]
I have no idea where to even begin as the index is 'unknown' (ie. given by the user when the function is called)
List items are referenced via their index and nested lists can work the same way.
If your list were:
list = [['nest1_1', 'nest1_2']['nest2_1', 'nest2_2']]
You could change it in the following ways:
list[0] = ['nesta_1', 'nesta_2']
list[1][0] = 'second_1'
This would make your list now be:
[['nesta_1', 'nesta_2']['second_1', 'nest2_2']]
Try this code:
data = [[1,2,3],[4,5,6]]
def element_change(data, index_list, element_to_change, change):
a =''.join([ str(i) for i in data[index_list]])
data[index_list][a.find(str(element_to_change))] = change
return data
print(element_change(data, 0, 2, 6))
Input:
[[1, 2, 3], [4, 5, 6]]
Output:
[[1, 6, 3], [4, 5, 6]]
Simply what it does is casting list to string and merging them in order to be able to use find() method to find the index.

Array Indexing in Python

Beginner here, learning python, was wondering something.
This gives me the second element:
list = [1,2,3,4]
list.index(2)
2
But when i tried this:
list = [0] * 5
list[2] = [1,2,3,4]
list.index[4]
I get an error. Is there some way to pull the index of an element from an array, no matter what list it's placed into? I know it's possible with dictionaries:
info = {first:1,second:2,third:3}
for i in info.values:
print i
1
2
3
Is there something like that for lists?
The index method does not do what you expect. To get an item at an index, you must use the [] syntax:
>>> my_list = ['foo', 'bar', 'baz']
>>> my_list[1] # indices are zero-based
'bar'
index is used to get an index from an item:
>>> my_list.index('baz')
2
If you're asking whether there's any way to get index to recurse into sub-lists, the answer is no, because it would have to return something that you could then pass into [], and [] never goes into sub-lists.
list is an inbuilt function don't use it as variable name it is against the protocol instead use lst.
To access a element from a list use [ ] with index number of that element
lst = [1,2,3,4]
lst[0]
1
one more example of same
lst = [1,2,3,4]
lst[3]
4
Use (:) semicolon to access elements in series first index number before semicolon is Included & Excluded after semicolon
lst[0:3]
[1, 2, 3]
If index number before semicolon is not specified then all the numbers is included till the start of the list with respect to index number after semicolon
lst[:2]
[1, 2]
If index number after semicolon is not specified then all the numbers is included till the end of the list with respect to index number before semicolon
lst[1:]
[2, 3, 4]
If we give one more semicolon the specifield number will be treated as steps
lst[0:4:2]
[1, 3]
This is used to find the specific index number of a element
lst.index(3)
2
This is one of my favourite the pop function it pulls out the element on the bases of index provided more over it also remove that element from the main list
lst.pop(1)
2
Now see the main list the element is removed..:)
lst
[1, 3, 4]
For extracting even numbers from a given list use this, here i am taking new example for better understanding
lst = [1,1,2,3,4,44,45,56]
import numpy as np
lst = np.array(lst)
lst = lst[lst%2==0]
list(lst)
[2, 4, 44, 56]
For extracting odd numbers from a given list use this (Note where i have assingn 1 rather than 0)
lst = [1,1,2,3,4,44,45,56]
import numpy as np
lst = np.array(lst)
lst = lst[lst%2==1]
list(lst)
[1, 1, 3, 45]
Happy Learning...:)
In your second example, your list is going to look like this:
[0, 0, [1, 2, 3, 4], 0, 0]
There's therefore no element 4 in the list.
This is because when you set list[2], you are changing the third element, not updating further elements in the list.
If you want to replace a range of values in the list, use slicing notation, for example list[2:] (for 'every element from the third to the last').
More generally, the .index method operates on identities. So the following will work, because you're asking python where the particular list object you inserted goes in the list:
lst = [0]*5
lst2 = [1,2,3,4]
lst[2] = lst2
lst.index(lst2) # 2
The answer to your question is no, but you have some other issues with your code.
First, do not use list as a variable name, because its also the name of the built-in function list.
Secondly, list.index[4] is different than list.index(4); both will give errors in your case, but they are two different operations.
If you want to pull the index of a particular element then index function will help. However, enumerate will do similar to the dictionary example,
>>> l=['first','second','third']
>>> for index,element in enumerate(l):
... print index,element
...
output
0 first
1 second
2 third

Categories

Resources