<jupyter_start><jupyter_text>Lists in PythonPython knows a number of compound data types, used to group together other values. The most versatile is the list, which can be written as a list of comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type.<jupyter_code>squares = [1, 4, 9, 16, 25]
print(squares)
example = [1,'Python',25.345,True]
print(example)<jupyter_output>[1, 4, 9, 16, 25]
[1, 'Python', 25.345, True]<jupyter_text>List items are ordered, changeable, and allow duplicate values ,meaning:* that the items have a defined order, and that order will not change.* we can change, add, and remove items in a list after it has been created and * since lists are indexed, lists can have items with the same value:**List items are indexed, the first item has index [0], the second item has index [1] etc.**Other way to index a list is **Negative Indexing**Negative indexing means start from the end`-1` refers to the last item, `-2` refers to the second last item etc.<jupyter_code>colors = ['red', 'blue', 'green']
print('First color: ',colors[0])    # red
print('Third color: ',colors[2])    # green
print('First color using negative indexing: ',colors[-3])    # red
print('Third color using negative indexing: ',colors[-1])    # green<jupyter_output>First color:  red
Third color:  green
First color using negative indexing:  red
Third color using negative indexing:  green<jupyter_text>Assignment with an = on lists **does not make a copy**. Instead, assignment makes the two variables point to the one list in memory.Below we will cofirm this using the **id()** function provided by python.The **id()** function returns a unique id for the specified object.We can see that the **id()** returns same value for **colors** and **b**<jupyter_code>b=colors
print('id of b     : ',id(b))
print('id of colors: ',id(colors))<jupyter_output>id of b     :  140663671669456
id of colors:  140663671669456<jupyter_text>Python List SlicingIn Python, list slicing is a common practice and it is the most used technique for programmers to solve efficient problems. Consider a python list, In-order to access a range of elements in a list, you need to slice a list. One way to do this is to use the simple slicing operator i.e. colon(:)With this operator, one can specify where to start the slicing, where to end, and specify the step. List slicing returns a new list from the existing list.**Syntax:**  `Lst[ Initial : End : IndexJump ]`  If Lst is a list, then the above expression returns the portion of the list from index Initial to index End, at a step size IndexJump.**NOTE** : Value at Initial index i.e `Lst[Index]` is included and `Lst[End]` is exluded.   Slicing using Positive Indexes<jupyter_code>## Notice in the examples below that the End Index is excluded

# Initialize list
Lst = [50, 70, 30, 20, 90, 10, 50]

# Positive slicing example
print('Positive Slicing example ',Lst[1:5:2])

# If start index not specified by default it starts from the beginning
print('Leaving out the start index ',Lst[:5:2])

#Not mandatory to specify the IndexJump...default value is 1
print('Leaving out the Start index and Index Jump',Lst[:4])

# If start index not specified by default it goes till the end
print('Leaving out the End index and Index Jump',Lst[2:])<jupyter_output>Positive Slicing example  [70, 20]
Leaving out the start index  [50, 30, 90]
Leaving out the Start index and Index Jump [50, 70, 30, 20]
Leaving out the End index and Index Jump [30, 20, 90, 10, 50]<jupyter_text>Slicing using Negative IndexesIndex **-1** represents the **last element** and **-n** represents the **first element** of the list(considering n as the length of the list). Similarly -2 represents second last, -3 --> third last and so on. Lists can be manipulated using negative indexes also.<jupyter_code># Initialize list
Lst = [50, 70, 30, 20, 90, 10, 50]
  
# Negative Slicing example
print('Negative Slicing example ',Lst[-5:-2:2])

# If start index not specified by default it starts from the beginning
print('Leaving out the start index ',Lst[:-2:2])

#Not mandatory to specify the IndexJump...default value is 1
print('Leaving out the Start index and Index Jump',Lst[:-2])

# If start index not specified by default it goes till the end
print('Leaving out the End index and Index Jump',Lst[-4:])<jupyter_output>Negative Slicing example  [30, 90]
Leaving out the start index  [50, 30, 90]
Leaving out the Start index and Index Jump [50, 70, 30, 20, 90]
Leaving out the End index and Index Jump [20, 90, 10, 50]<jupyter_text>Changing Items of ListYou can change items in the list by refering the position at which you want to change by indexing and assigning the new value to it.    Range of indexes can also be change in one go by refering to a slice and then assigning it a new list of values. The resultant length of the list changes depending upon the length of the slice refered and the length of list of values it is assigned.    Refer the following examples and their output for a better understanding:<jupyter_code>print('Change the second item')
thislist = ["apple", "banana", "cherry"]
thislist[1] = "blackcurrent"
print(thislist)

print('Change the values "banana" and "cherry" with the values "blackcurrant" and "watermelon"')
thislist = ["apple", "banana", "cherry", "orange", "kiwi", "mango"]
thislist[1:3] = ["blackcurrent", "watermelon"]
print(thislist)

""""If you insert more items than you replace
the new items will be inserted where you specified, and the remaining items will move accordingly"""

print('Change the second value by replacing it with two new values')
thislist = ["apple", "banana", "cherry"]
thislist[1:2] = ["blackcurrent", "watermelon"]
print(thislist)

""""If you insert less items than you replace
the new items will be inserted where you specified, and the remaining items will move accordingly"""

print('Change the second and third value by replacing it with one value')
thislist = ["apple", "banana", "cherry"]
thislist[1:3] = ["watermelon"]
print(thislist)<jupyter_output>Change the second item
['apple', 'blackcurrent', 'cherry']
Change the values "banana" and "cherry" with the values "blackcurrant" and "watermelon"
['apple', 'blackcurrent', 'watermelon', 'orange', 'kiwi', 'mango']
Change the second value by replacing it with two new values
['apple', 'blackcurrent', 'watermelon', 'cherry']
Change the second and third value by replacing it with one value
['apple', 'watermelon']<jupyter_text>len() returns the **number of items in the object passed** (here, list)<jupyter_code>len([10,20,30,40,50])<jupyter_output><empty_output><jupyter_text>RangeThe range(n) function yields the numbers 0, 1, ... n-1, and range(a, b) returns a, a+1, ... b-1 -- up to but not including the last number. The combination of the for-loop and the range() function allow you to build a traditional numeric for loop:<jupyter_code>## print the numbers from 0 through 99
for i in range(5):
   print(i)<jupyter_output>0
1
2
3
4<jupyter_text>List Methods Here are some other common list methods.* list.append(elem) -- adds a single element to the end of the list. Common error: does not return the new list, just modifies the original.* list.insert(index, elem) -- inserts the element at the given index, shifting elements to the right.* list.extend(list2) adds the elements in list2 to the end of the list. Using + or += on a list is similar to using extend().* list.index(elem) -- searches for the given element from the start of the list and returns its index. Throws a ValueError if the element does not appear (use "in" to check without a ValueError).* list.remove(elem) -- searches for the first instance of the given element and removes it (throws ValueError if not present)* list.sort() -- sorts the list in place (does not return it). (The sorted() function shown later is preferred.)* list.reverse() -- reverses the list in place (does not return it)* list.pop(index) -- removes and returns the element at the given index. Returns the rightmost element if index is omitted (roughly the opposite of append()).    Notice that these are *methods* on a list object, while len() is a function that takes the list (or string or whatever) as an argument.  Inserting ItemsTo insert a new list item, without replacing any of the existing values, we can use the insert() method.The **insert()** method inserts an item at the specified index:<jupyter_code># Insert "watermelon" as the third item:
thislist = ["apple", "banana", "cherry"]
thislist.insert(2, "watermelon")
print(thislist)<jupyter_output>['apple', 'banana', 'watermelon', 'cherry']<jupyter_text>Append ItemsTo add an item to the end of the list, use the **append()** method:<jupyter_code># Using the append() method to append an item:
thislist = ["apple", "banana", "cherry"]
thislist.append("orange")
print(thislist)<jupyter_output>['apple', 'banana', 'cherry', 'orange']<jupyter_text>Extend ListTo append elements from another list to the current list, use the **extend()** method. The elements will be added to the end of the list.The extend() method does not have to append lists, you can **add any iterable object** (tuples, sets, dictionaries etc).<jupyter_code>thislist = ["apple", "banana", "cherry"]
tropical = ["mango", "pineapple", "papaya"]
thislist=thislist+tropical
print(thislist)<jupyter_output>['apple', 'banana', 'cherry', 'mango', 'pineapple', 'papaya']<jupyter_text>Remove Elements Following are some inbuilt python functions to delete items in a list. We can choose the method we want want to use from the below options depending upon our use case.* The **remove(`Value`)** method removes the specified item.* The **pop(`Index`)** method removes the specified index.* The **del(`Index`)** keyword also removes the specified index.* The **clear()** method empties the list. The list still remains, but it has no content.   **Examples of implementation of the above mentioned functions is shown below :**<jupyter_code>#Remove "banana":
print('remove() function :')
thislist = ["apple", "banana", "cherry"]
thislist.remove("banana")
print(thislist)

#Remove the second item:
print('pop() function :')
thislist = ["apple", "banana", "cherry"]
thislist.pop(1)
print(thislist)

#If you do not specify the index, the pop() method removes the last item.
#Remove the last item:
print('pop() function :')
thislist = ["apple", "banana", "cherry"]
thislist.pop()
print(thislist)

#Remove the first item:
print('del() function :')
thislist = ["apple", "banana", "cherry"]
del thislist[0]
print(thislist)

#Delete the entire list:
print('del() function :')
thislist = ["apple", "banana", "cherry"]
del thislist
#If we uncomment the below line we will encounter an error because the list itself is deleted 
#print(thisList)

#Clear the list content:
print('clear() function :')
thislist = ["apple", "banana", "cherry"]
thislist.clear()
#Here we do not encounter error when we print as only the list items are deleted, not the list itself
print(thislist)<jupyter_output>remove() function :
['apple', 'cherry']
pop() function :
['apple', 'cherry']
pop() function :
['apple', 'banana']
del() function :
['banana', 'cherry']
del() function :
clear() function :
[]<jupyter_text>Looping through a ListSome of the methos to loop through a list are :* You can loop through the list items by using a for loop* You can also loop through the list items by referring to their index numberby using the range() and len() functions to create a suitable iterable.* You can loop through the list items by using a while loop.    Use the len() function to determine the length of the list, then start at 0 and loop your way through the list     items by refering to their indexes.    Remember to increase the index by 1 after each iteration.* List Comprehension offers the shortest syntax for looping through listsFollowing is the implementation for the above methods to print all items in the list, one by one :<jupyter_code>thislist = ["apple", "banana", "cherry"]

print('1st method :')
for x in thislist:
  print(x)
print('\n2nd method :')
for i in range(len(thislist)):
  print(thislist[i])

print('\n3rd method :')
i = 0
while i < len(thislist):
  print(thislist[i])
  i = i + 1

print('\n4th method :')
[print(x) for x in thislist]<jupyter_output>1st method :
apple
banana
cherry

2nd method :
apple
banana
cherry

3rd method :
apple
banana
cherry

4th method :
apple
banana
cherry<jupyter_text>List Comprehension    List comprehensions provide a concise way to create lists. Common applications are to make new lists where each element is the result of some operations applied to each member of another sequence or iterable, or to create a subsequence of those elements that satisfy a certain condition.For example, assume we want to create a list of squares, like:<jupyter_code>squares = []
for x in range(10):
    squares.append(x**2)
squares<jupyter_output><empty_output><jupyter_text>**Note** : This creates (or overwrites) a variable named x that still exists after the loop completes.   We can calculate the list of squares without any side effects using:<jupyter_code>squares = list(map(lambda x: x**2, range(10)))
print(squares)
#OR USING 
squares = [x**2 for x in range(10)]
print(squares)<jupyter_output>[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]<jupyter_text>A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it. For example, this listcomp combines the elements of two lists if they are not equal:<jupyter_code>[[x, y] for x in [1,2,3] for y in [3,1,4] if x != y]
combs = []
for x in [1,2,3]:
    for y in [3,1,4]:
        if x != y:
            combs.append([x, y])
combs<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10469962632940501, 'fraction_numerical': 0.01925840758838747, 'mean_word_length': 5.071989528795812, 'pattern_counts': {'":': 1, '<': 53, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '412844', 'license': 'MIT', 'n_tokens_mistral': 4299, 'n_tokens_neox': 4032, 'n_words': 1944, 'path': 'python-numpy-basics/Lists.ipynb', 'repo_name': 'chaitravi-ce/Intro_to_CV', 'size': '13916'}