Delete empty value from (sorted) dictionary - python

I've got an arduino sending me serial data which is transposed into a dictionary.
However, not all entries have a value due data being sent at random.
Before sending the dictionary data to a CSV file I want to prune the empty values or values that are 0 from the dict.
Incoming data would look like this: (values only)
['','7','','49,'','173','158']
I want that to become
['7','49','173','158].
The script I currently use:
import serial
import time
def delete_Blanks(arrayName):
tempArray = array.copy()
for key, value in sorted(tempArray.items()):
if value == "":
del tempArray[key]
else:
print "Value is not nil"
return tempArray
array = {}
ser = serial.Serial('COM2', 9600, timeout=1)
key = 0
while 1:
length = len(array)
if len(array) in range(0,5):
array.update({key:ser.read(1000)})
key = key + 1
print "key is ", key
print array.values()
length = len(array)
else:
newArray = delete_Blanks(array)
print newArray.items()
break

from itertools import compress
l = ['','7','','49','','173','158']
ret = compress(l, map(lambda x: bool(x), l))
print(list(ret))
will output:
['7', '49', '173', '158']
if you have long arrays of data - it's better to work with iterators to avoid memory leaks. If you work with short lists - list comprehension is just fine

You can use a dictionary comprehension. This will remove all false values from a dictionary d:
d={key,d[key] for key in d if d[key]}

If it's just a plain list you can do something like this
Mylist = filter(None, Mylist)
Before creating the dictionary you can filter the two list, the list containing the keys and the list containing the values. Assuming both list are the same length you can then
mydict = dict(zip(l1, l2))
to create your new list

>>> li = ['','7','','49','','173','158']
>>> [e for e in li if e]
['7', '49', '173', '158']

Related

Converting two lists into a dictionary using built in list function?

I have been trying this for weeks! I tried this for weeks and all i get is nothing!
I searched internet and also the great STACK OVERFLOW but I couldn't find the one i need for!
Well normally if we try to change lists into dictionary we would get space between key and value!
for example:
Output:
The result dict is : {'Stack': '10'}
Well, I want the output as follows:
The result dict is : {'Stack':'10'}
Well the zip function would give a space between them and cause me an error!
And this is the result I have to get:
Enter list elements separated by ,(Comma) for list1: Stack,Over,Flow
Enter list elements separated by ,(Comma) for list2: 111,222,333
{'Stack':'111','Over':'222','Flow':'333'}
and for the code I tried is:
List_1 = input('Enter list elements separated by ,(Comma): ').split(',')
List_2 = input('Enter list elements separated by ,(Comma): ').split(',')
if len(List_1) == len(List_2) and len(List_1) != 0 and len(List_2) != 0 :
dict = dict(zip(List_1, List_2))
print(dict)
else:
print('The two lists are of different lengths. Try again.')
Since you want to be quite specific about the output I would do something like this:
def condensed_dict(data):
output = []
for item in data.items():
output.append('%r:%r' % item)
return '{%s}' % ''.join(output)
List_1 = input('Enter list elements separated by ,(Comma): ').split(',')
List_2 = input('Enter list elements separated by ,(Comma): ').split(',')
if List_1 and len(List_1) == len(List_2):
dict = dict(zip(List_1, List_2))
print(condensed_dict(dict))
else:
print('The two lists are of different lengths. Try again.')
PS: I simplified your if statement a bit.
Build your own string from the zipped lists directly, rather than using a dict.
>>> "{%s}" % ",".join(f"'{k}':'{v}'" for k, v in zip(List_1, List_2))
"{'Stack':'111','Over':'222','Flow':'333'}"
If you already have the dict, then build the string from the output of its items method.
>>> d = dict(zip(List_1, List2))
>>> "{%s}" % ",".join(f"'{k}':'{v}'" for k, v in d.items())
"{'Stack':'111','Over':'222','Flow':'333'}"
test_keys = ["Rash", "Kil", "Varsha"]
test_values = [1, 4, 5]
print ("Original key list is : " + str(test_keys))
print ("Original value list is : " + str(test_values))
# using zip()
# to convert lists to dictionary
res = dict(zip(test_keys, test_values))
print ("Resultant dictionary is : " + str(res))

is there a way to avoid nested loop

I'm given two different data and I'm wondering if there is a way to get specific data without using nested loop
firstdata = [[["key"],["value"]],
[[2],["two"]],
[[3],["three"]]]
seconddata = [[[key],["artimatic"]],
[[2],["0+2"]],
[[2],["1+1"]],
[[3],["0+3"]],
[[3],["1+2"]],
[[3],["2+1"]]]
//nested loop solution would look like this
for x in firstdata:
for y in seconddata:
print(x[1])
if x[0]==y[0]:
print(y)
Is there an alternative solution that I can loop the seconddata without using nested loop?
**Ok I am assuming Data Structure of firstdata and seconddata will be same:
firstdata_dict = {x[0][0]: x[1][0] for x in firstdata}
seconddata_dict = {}
for data in seconddata:
if not seconddata_dict.has_key(data[0][0]):
seconddata_dict[data[0][0]] = []
seconddata_dict[data[0][0]].append(data[1][0])
for key, value in firstdata_dict.items():
if seconddata_dict.get(key):
# key match add your algo
print seconddata_dict[key]
Output:
['0+2', '1+1']
['0+3', '1+2', '2+1']
['artimatic']
Start by converting the list to a dictionary as so. Here the keys are the numbers 2 and 3, and values are list of strings associated to a specific key in the list
def convert_to_dct(lst):
dct = {}
for x in lst:
for i in range(len(x)):
key = x[0][0]
value = x[1][0]
if key in dct:
dct[key].append(value)
else:
dct[key] = []
return dct
This function converts the list as follows
firstdata = [[["key"],["value"]],
[[2],["two"]],
[[3],["three"]]]
seconddata = [[["key"],["artimatic"]],
[[2],["0+2"]],
[[2],["1+1"]],
[[3],["0+3"]],
[[3],["1+2"]],
[[3],["2+1"]]]
firstdict = convert_to_dct(firstdata)
seconddict = convert_to_dct(seconddata)
print(firstdict)
print(seconddict)
#{'key': ['value'], 2: ['two'], 3: ['three']}
#{'key': ['artimatic'], 2: ['0+2', '1+1', '1+1'], 3: ['0+3', '1+2', '1+2', '2+1', '2+1']}
Then to get your final result, do
for key in firstdict.keys():
if key in seconddict.keys():
print(seconddict[key])
#['artimatic']
#['0+2', '1+1', '1+1']
#['0+3', '1+2', '1+2', '2+1', '2+1']
I don't think the two answers understand the question correctly, so here you go:
Create your data
firstData = [[["key"],["value"]],
[[2],["two"]],
[[3],["three"]]]
secondData = [[['key'],["artimatic"]],
[[2],["0+2"]],
[[2],["1+1"]],
[[3],["0+3"]],
[[3],["1+2"]],
[[3],["2+1"]]]
Then
firstdata_dict = {x[0][0]: x[1][0] for x in firstData} #Creates the dictionary of first Data
Then do the computation
for element in secondData:
if (element[0][0] in firstdata_dict): #Checks in a hashMap and is thus done in O(1) generally
print(element)

While loop within for loop for list of lists

I'm trying to create a big list that will contain lists of strings. I iterate over the input list of strings and create a temporary list.
Input:
['Mike','Angela','Bill','\n','Robert','Pam','\n',...]
My desired output:
[['Mike','Angela','Bill'],['Robert','Pam']...]
What i get:
[['Mike','Angela','Bill'],['Angela','Bill'],['Bill']...]
Code:
for i in range(0,len(temp)):
temporary = []
while(temp[i] != '\n' and i<len(temp)-1):
temporary.append(temp[i])
i+=1
bigList.append(temporary)
Use itertools.groupby
from itertools import groupby
names = ['Mike','Angela','Bill','\n','Robert','Pam']
[list(g) for k,g in groupby(names, lambda x:x=='\n') if not k]
#[['Mike', 'Angela', 'Bill'], ['Robert', 'Pam']]
Fixing your code, I'd recommend iterating over each element directly, appending to a nested list -
r = [[]]
for i in temp:
if i.strip():
r[-1].append(i)
else:
r.append([])
Note that if temp ends with a newline, r will have a trailing empty [] list. You can get rid of that though:
if not r[-1]:
del r[-1]
Another option would be using itertools.groupby, which the other answerer has already mentioned. Although, your method is more performant.
Your for loop was scanning over the temp array just fine, but the while loop on the inside was advancing that index. And then your while loop would reduce the index. This caused the repitition.
temp = ['mike','angela','bill','\n','robert','pam','\n','liz','anya','\n']
# !make sure to include this '\n' at the end of temp!
bigList = []
temporary = []
for i in range(0,len(temp)):
if(temp[i] != '\n'):
temporary.append(temp[i])
print(temporary)
else:
print(temporary)
bigList.append(temporary)
temporary = []
You could try:
a_list = ['Mike','Angela','Bill','\n','Robert','Pam','\n']
result = []
start = 0
end = 0
for indx, name in enumerate(a_list):
if name == '\n':
end = indx
sublist = a_list[start:end]
if sublist:
result.append(sublist)
start = indx + 1
>>> result
[['Mike', 'Angela', 'Bill'], ['Robert', 'Pam']]

Python - Nested Lists

I'm trying to cross check two nested list values, and if I get a match, append the values from list1 into list2.
For example;
list1 = [[ip, hostname], [ip, hostname], [ip, hostname]]
list2 = [[ip, ip_upper, type, hostname, location], [ip, ip_upper, type, hostname, location], [ip, ip_upper, type, hostname, location]]
I want to check if the value in list1[x][0] is in list2, if so, replace the value of List2[x][3] with List1[x][1].
What I'm attempting is;
count = 0;
for row in list2:
if row[0] in hosts[count][0]:
new_hostname = hosts[count][1]
row[4].append(new_hostname)
count += 1
else:
continue
count += 1
I know the above is incorrect, i'm struggling to figure out how to access the values list1 whilst traversing list2. The reason is because I need to check each row, and then the value with the row and then amend specific values within the row.
Thanks for the RAPID response!
I've tried to implement the code given but am running into trouble when trying to create a diction from my list:
wow, you guys!
def doStuff(list1, list2):
mydic = dict(list2)
for l in list1:
l[3] = mydic.get(l[0], l[3])
return mydic
new_dic = doStuff(hostname, old_rows)
I'm receiving the error;
mydic = dict(list2)
ValueError: dictionary update sequence element #0 has length 6; 2 is required
Any ideas?
This works fine i guess, and its time complexity is only O(n + m) with n and m being the length of each list.
def doStuff(list1, list2):
mydic = dict(list1)
for l in list2:
l[3] = mydic.get(l[0], l[3])
Assuming the ip field value supports equality comparison (==), this solution may help you. It's quite plain and lame and probably not very optimised, but it works.
Note: it works for every occurrence of each element of list1 in list2, so if you had multiple matches in list2, they would all get updated.
list1 = [['1.2.3.4', 'ciao.com'],
['1.2.3.5', 'prova.net'],
['1.2.2.2', 'uovo.net']]
list2 = [['1.2.3.4', '1.2.3.x', 'type', 'xyz.com', 'puglia'],
['1.2.3.7', '1.2.3.x', 'type', 'zyx.com', 'lazio'],
['1.2.3.5', '1.2.3.x', 'type', 'yxz.com', 'molise']]
print list1
print list2
for i in list1:
ip = i[0]
for j in list2:
cur_ip = j[0]
if ip == cur_ip:
j[3] = i[1]
print list2
outputs:
[['1.2.3.4', 'ciao.com'], ['1.2.3.5', 'prova.net'], ['1.2.2.2', 'uovo.net']]
[['1.2.3.4', '1.2.3.x', 'type', 'xyz.com', 'puglia'], ['1.2.3.7', '1.2.3.x', 'type', 'zyx.com', 'lazio'], ['1.2.3.5', '1.2.3.x', 'type', 'yxz.com', 'molise']]
[['1.2.3.4', '1.2.3.x', 'type', 'ciao.com', 'puglia'], ['1.2.3.7', '1.2.3.x', 'type', 'zyx.com', 'lazio'], ['1.2.3.5', '1.2.3.x', 'type', 'prova.net', 'molise']]
Sort the target list on ip then use itertools.groupby to iterate over the targets. It may have a slight advantage if there are a lot of items in list2 that don't need to be modified (they are skipped).
import operator, itertools
ip = operator.itemgetter(0)
keys = dict(list1)
list2.sort(key = ip)
for key, group in itertools.groupby(list2, ip):
if key in keys:
for item in group:
item[3] = keys[key]

Python : Find Duplicate Items

I have data in columns of csv .I have an array from two columns of it.Iam using a List of list . I have string list like this
[[A,Bcdef],[Z,Wexy]
I want to identify duplicate entries i.e [A,Bcdef] and [A,Bcdef]
import csv
import StringIO
import os, sys
import hashlib
from collections import Counter
from collections import defaultdict
from itertools import takewhile, count
columns = defaultdict(list)
with open('person.csv','rU') as f:
reader = csv.DictReader(f) # read rows into a dictionary format
listoflists = [];
for row in reader: # read a row as {column1: value1, column2: value2,...}
a_list = [];
for (c,n) in row.items():
if c =="firstName":
try:
a_list.append(n[0])
except IndexError:
pass
for (c,n) in row.items():
if c=="lastName":
try:
a_list.append(n);
except IndexError:
pass
#print list(a_list);
listoflists.append(a_list);
#i += 1
print len(listoflists);
I have tried a couple of solutions proposed here
Using set (listoflist) always returns :unhashable type: 'list'
Functions : returns : 'list' object has no attribute 'values'
For example:
results = list(filter(lambda x: len(x) > 1, dict1.values()))
if len(results) > 0:
print('Duplicates Found:')
print('The following files are identical. the content is identical')
print('___________________')
for result in results:
for subresult in result:
print('\t\t%s' % subresult)
print('___________________')
else:
print('No duplicate files found.')
Any suggestions are welcomed.
Rather than lists, you can use tuples which are hashable.
You could build a set of the string representations of you lists, which are quite hashable.
l = [ ['A', "BCE"], ["B", "CEF"], ['A', 'BCE'] ]
res = []
dups = []
s = sorted(l, key=lambda x: x[0]+x[1])
previous = None
while s:
i = s.pop()
if i == previous:
dups.append(i)
else:
res.append(i)
previous = i
print res
print dups
Assuming you just want to get rid of duplicates and don't care about the order, you could turn your lists into strings, throw them into a set, and then turn them back into a list of lists.
foostrings = [x[0] + x[1] for x in listoflists]
listoflists = [[x[0], x[1:]] for x in set(foostrings)]
Another option, if you're going to be dealing with a bunch of tabular data, is to use pandas.
import pandas as pd
df = pd.DataFrame(listoflists)
deduped_df = df.drop_duplicates()

Categories

Resources