Get the group ID sorted from "/etc/group" - python-3.x

I'd like to manipulate the "/etc/group"
In [39]: fp = open("/etc/group")
In [40]: content = [c.replace("\n", "") for c in fp.readlines()]
In [42]: content
Out[42]:
['root:x:0:',
'bin:x:1:',
'daemon:x:2:',
'sys:x:3:',
'adm:x:4:',
'tty:x:5:',
'disk:x:6:',
'lp:x:7:',
'mem:x:8:',
'kmem:x:9:',
'wheel:x:10:',
'cdrom:x:11:',
'mail:x:12:postfix',
'man:x:15:',
'dialout:x:18:',....]
The result is sorted by alphabet rather than the group ID
In [44]: sorted(content, key=lambda c:int(re.search(r"\d+",c).group()))
Out[44]:
['root:x:0:',
'bin:x:1:',
'daemon:x:2:',
'sys:x:3:',
'adm:x:4:',
'tty:x:5:',
'disk:x:6:',
'lp:x:7:',
'mem:x:8:',
'kmem:x:9:',
'wheel:x:10:',
'cdrom:x:11:',
'mail:x:12:postfix',
'man:x:15:',
'dialout:x:18:',
I get it done with re.search and lambda in a unwired way,
Could it be solved in an elegant style?

Sort by the third colon-defined field:
sorted(content, key=lambda x: int(x.split(':')[2]))

Related

How to apply recursion over this problem and solve this problem

The Problem is:-
Given a digit string, return all possible letter combinations of each digits according to the buttons on a telephone, that the number could represent.
The returned strings must be lexicographically sorted.
Example-1 :-
Input : “23”
Output : ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]
Example-2 :-
Input : “9”
Output: [“w”, “x”, “y”, “z”]
Example-3 :-
Input : “246”
Output : ["agm", "agn", "ago", "ahm", ..., "cho", "cim", "cin" "cio"] {27 elements}
I've squeezed my brain on this, and I've tried a lot but I'm not getting ahead of this part, what I've tried is to use a recursive function that zips the individual letters of each digit with each other letters and use itertools.combinations() over it, but I'm unable to complete this function and I'm unable to get ahead of this.
What I've tried is :-
times, str_res = 0, ""
def getval(lst, times):
if times==len(lst)-1:
for i in lst[times]:
yield i
else:
for i in lst[times]:
yield i + getval(lst, times+1)
dct = {"2":("a","b","c"), "3":("d","e","f"), "4":("g","h","i"),
"5":("j","k","l"), "6":("m","n","o"), "7":("p","q","r","s"),
"8":("t","u","v"), "9":("w","x","y","z"), "1":("")}
str1, res = "23", []
if len(str1)==1:
print(dct[str1[0]])
else:
temp = [dct[i] for i in str1]
str_res = getval(temp, times)
print(str_res)
Please suggest me your ideas over this problem or in completing the function...
It's not itertools.combinations that you need, it's itertools.product.
from itertools import product
def all_letter_comb(s, dct):
for p in product(*map(dct.get, s)):
yield ''.join(p)
dct = {"2":("a","b","c"), "3":("d","e","f"), "4":("g","h","i"),
"5":("j","k","l"), "6":("m","n","o"), "7":("p","q","r","s"),
"8":("t","u","v"), "9":("w","x","y","z"), "1":("")}
for s in ['23', '9', '246']:
print(s)
print(list(all_letter_comb(s, dct)))
print()
Output:
23
['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']
9
['w', 'x', 'y', 'z']
246
['agm', 'agn', 'ago', 'ahm', 'ahn', 'aho', 'aim', 'ain', 'aio', 'bgm', 'bgn', 'bgo', 'bhm', 'bhn', 'bho', 'bim', 'bin', 'bio', 'cgm', 'cgn', 'cgo', 'chm', 'chn', 'cho', 'cim', 'cin', 'cio']
If I am not wrong this is leet code problem. You can find multiple answers there.

Python Iterating through List of List

Heres my code
stockList = [
['AMD', '57.00', '56.23', '58.40', '56.51'],
['AMZN', '3,138.29', '3,111.03', '3242.56689', '3,126.58'],
['ATVI', '80.76', '79.16', '81.86', '79.55'],
['BA', '178.63', '168.86', '176.96', '169.70'],
['BAC', '24.42', '23.43', '23.95', '23.54'],
['DAL', '26.43', '25.53', '26.87', '25.66'],
['FB', '241.75', '240.00', '248.06', '241.20'],
['GE', '7.04', '6.76', '6.95', '6.79'],
['GOOGL', '1,555.92', '1,536.36', '1,576.03', '1,544.04'],
['GPS', '12.77', '12.04', '12.72', '12.10'],
['GRUB', '70.96', '69.71', '70.65', '70.06'],
['HD', '262.42', '258.72', '261.81', '260.01'],
['LUV', '33.62', '32.45', '33.53', '32.61'],
['MSFT', '208.75', '206.72', '213.58', '207.76'],
['MU', '51.52', '50.49', '52.31', '50.74'],
['NFLX', '490.10', '492.26', '511.52', '494.72', 'SUCCESS'],
['PCG', '9.49', '8.96', '9.52', '9.01'],
['PFE', '36.69', '35.87', '37.02', '36.05'],
['QQQ', '264.00', '263.27', '267.11', '264.58', 'SUCCESS'],
['ROKU', '153.36', '148.37', '153.70', '149.11'],
['SHOP', '952.83', '976.45', '1,036.25', '981.33', 'SUCCESS'],
['SPY', '325.01', '323.64', '325.47', '325.25', 'SUCCESS'],
['SQ', '126.99', '125.13', '130.80', '125.76'],
['T', '30.25', '29.58', '30.07', '29.73'],
['TSLA', '1,568.36', '1,646.56', '1,712.58', '1,654.79', 'SUCCESS'],
['TTWO', '153.06', '152.45', '154.47', '153.22', 'SUCCESS'],
['TWTR', '37.01', '36.03246', '36.7210083', '36.21'],
['WFC', '26.20', '24.45272', '25.0438213', '24.57'],
['WMT', '132.33', '130.8515', '132.522049', '131.51']
]
keyword = 'SUCCESS'
secondList = []
for item in stockList:
if item[4] == keyword:
secondList.append(stockList[0])
print(secondList)
My use case is, to go through this lists of list, find which list contains the keyword, from there send the first item in the list. I am able to get it with one single list, however I can't do it with a list of list.
On top of that, how would I go through a dictionary containing lists?
{
'majorDimension': 'ROWS',
'range': 'Sheet1!A2:F30',
'values': [
['AMD', '57.00', '56.23', '58.40', '56.51'],
['AMZN', '3,138.29', '3,111.03', '3242.56689', '3,126.58'],
['ATVI', '80.76', '79.16', '81.86', '79.55'],
['BA', '178.63', '168.86', '176.96', '169.70'],
['BAC', '24.42', '23.43', '23.95', '23.54'],
['DAL', '26.43', '25.53', '26.87', '25.66'],
['FB', '241.75', '240.00', '248.06', '241.20'],
['GE', '7.04', '6.76', '6.95', '6.79'],
['GOOGL', '1,555.92', '1,536.36', '1,576.03', '1,544.04'],
['GPS', '12.77', '12.04', '12.72', '12.10'],
['GRUB', '70.96', '69.71', '70.65', '70.06'],
['HD', '262.42', '258.72', '261.81', '260.01'],
['LUV', '33.62', '32.45', '33.53', '32.61'],
['MSFT', '208.75', '206.72', '213.58', '207.76'],
['MU', '51.52', '50.49', '52.31', '50.74'],
['NFLX', '490.10', '492.26', '511.52', '494.72', 'SUCCESS'],
['PCG', '9.49', '8.96', '9.52', '9.01'],
['PFE', '36.69', '35.87', '37.02', '36.05'],
['QQQ', '264.00', '263.27', '267.11', '264.58', 'SUCCESS'],
['ROKU', '153.36', '148.37', '153.70', '149.11'],
['SHOP', '952.83', '976.45', '1,036.25', '981.33', 'SUCCESS'],
['SPY', '325.01', '323.64', '325.47', '325.25', 'SUCCESS'],
['SQ', '126.99', '125.13', '130.80', '125.76'],
['T', '30.25', '29.58', '30.07', '29.73'],
['TSLA', '1,568.36', '1,646.56', '1,712.58', '1,654.79', 'SUCCESS'],
['TTWO', '153.06', '152.45', '154.47', '153.22', 'SUCCESS'],
['TWTR', '37.01', '36.03246', '36.7210083', '36.21'],
['WFC', '26.20', '24.45272', '25.0438213', '24.57'],
['WMT', '132.33', '130.8515', '132.522049', '131.51'],
]
}
List comprehension makes this pretty simple. Try the following:
keyword = "SUCCESS"
# PEP8 calls for lower_underscore_case here
second_list = [i[0] for i in stockList if keyword in i]
print(second_list)
For the proposed dictionary structure, you'd just access the key containing the list, since not every value in that dict is a list:
second_list = [i[0] for i in stockList["values"] if keyword in i]
Based upon your question understanding. Your question is divided into two parts, these are:
How to iterate over list of lists, and get the first item from the nested list, and store it in another list
How to iterate over dictionary item, to perform the same operation
If my understanding is right, then you might want to check this out.
Please note: I have not used variable keyword, simply used "SUCCESS", just replace keyword with "SUCCESS" in the code, and you are good to go.
1. FIRST SOLUTION
# to get nested list
for item in stockList:
# this checks whether SUCCESS is present inside a list
# python way of doing it
if "SUCCESS" in item: secondList.append(item[0])
print(secondList)
# OUTPUT
# >>> ['NFLX', 'QQQ', 'SHOP', 'SPY', 'TSLA', 'TTWO']
OR
You can do this in more pythonic way, that is to use List Comprehension
# single line approach, getting the same result
secondList = [item[0] for item in stockList if "SUCCESS" in item]
print(secondList)
# OUTPUT
# >>> ['NFLX', 'QQQ', 'SHOP', 'SPY', 'TSLA', 'TTWO']
2. SECOND SOLUTION
In order to get the result, first you need to assign the Dictionary to your variable, in my case, I have assigned to a variable called stockListDictionary
secondList = []
# to get a value from key specifically
# likt any dictionary key dictionary["key_name"]
for item in stockListDictionary["values"]:
if "SUCCESS" in item: secondList.append(item[0])
print(secondList)
# OUTPUT
# >>> ['NFLX', 'QQQ', 'SHOP', 'SPY', 'TSLA', 'TTWO']
OR
Using List Comprehension
secondList = [item[0] for item in stockListDictionary["values"] if "SUCCESS" in item]
print(secondList)
# OUTPUT
# >>> ['NFLX', 'QQQ', 'SHOP', 'SPY', 'TSLA', 'TTWO']
What about something like this?
keywords={"SUCCESS"}
d = # the dictionary
second_list = list()
for nested_lists in d["values"]:
for stock_info in nested_lists:
stock_ticker = stock_info[0]
if stock_ticker in keywords:
info = set(stock_info[1:])
if info & keywords:
second_list.append(stock_ticker)
Is this better? It should allow you to have more than one keyword.

Create a dictionary from two lists having duplicate elements

Create a dictionary from two lists having duplicate elements where list 1 is the key of the new dictionary and for all strings in list 2 that exactly match list 1, append it to its values field for the keys in list 1. So, for example:
{'assembla':['assemblabase', 'assemblauploading']}
Like this, I want for each element in list 1
Stuck in this logic:
new_d = {}
for j in list2:
if j == list1 :
new_d['j'].get('j')
print(new_d)
List 1:
list1 = ['assembla', 'bitbucket', 'cloudapp', 'cloudforge', 'cloudinary', 'concur', 'confluence', 'convo', 'dochub', 'docstoc', 'docusign', 'draw.io', 'dropbox', 'egnyte', 'evernote', 'facebook', 'flickr', 'github', 'gitlab', 'glassdoor', 'globalmeet', 'gotowebinar', 'hightail', 'hootsuite', 'huddle', 'icloud', 'imgur', 'instagram', 'issuu', 'jumpshare', 'linkedin', 'lucidpress', 'mail.ru', 'maytech', 'meetup', 'mega', 'mendeley', 'mixi', 'myspace', 'ning', 'onehub', 'owncloud', 'pastebin', 'pinterest', 'prezi', 'proofhub', 'quip', 'quora', 'readytalk', 'reddit', 'renren', 'screencast', 'scribd', 'sendthisfile', 'sharevault', 'slack', 'slideshare', 'smartsheet', 'soundcloud', 'sourceforge', 'stocktwits', 'storify', 'surveymonkey', 'syncplicity', 'tableau', 'teamdrive', 'teamviewer', 'trello', 'tumblr', 'twitter', 'viber', 'vimeo', 'vine', 'virustotal', 'workday', 'yammer', 'youtube', 'zendesk', 'zenefits']
List 2:
list2 = ['2ch', '2chbase', '2chposting', '51.com', '51.commail', '51.combase', '51.combbs', '51.composting', '51.comwebdisk', '51.commusic', '51.comgames', 'adobeconnect', 'adobemeeting', 'adobemeetingdesktopsharing', 'adobemeetinguploading', 'adobemeetingfiletransfer', 'adobemeetingremotecontrol', 'adobeconnectnow', 'adobeconnectnowbase', 'adobeconnectnowfiletransfer', 'adobeconnectnowremotecontrol', 'adobecreativecloud', 'adobecreativecloudbase', 'adobecreativeclouduploading', 'aim', 'aimbase', 'aimvideo', 'aimaudio', 'aimfiletransfer', 'aimexpress', 'aimexpressbase', 'aimexpressfiletransfer', 'aliwangwang', 'aliwangwangbase', 'aliwangwangaudiovideo', 'aliwangwangfiletransfer', 'aliwangwangremotecontrol', 'amazonclouddrive', 'amazonclouddrivebase', 'amazonclouddriveuploading', 'amazonmusic', 'amazonmusicbase', 'amazonmusicstreaming', 'amebanow', 'amebanowbase', 'amebanowposting', 'assembla', 'assemblabase', 'assemblauploading', 'autodesk360', 'autodesk360base', 'autodesk360uploading', 'avayawebalive', 'avayawebalivebase', 'avayawebalivedesktopsharing', 'avayawebalivevoice', 'avayawebalivefiletransfer', 'bacnet', 'bacnetbase', 'bacnetackalarm', 'bacnetconfirmedcovnotify', 'bacnetconfirmedeventnotify', 'bacnetgetalarmsummary', 'bacnetgetenrollmentsummary', 'bacnetsubscribecov', 'bacnetatomicreadfile', 'bacnetatomicwritefile', 'bacnetaddlistelement', 'bacnetremovelistelement', 'bacnetcreateobject', 'bacnetdeleteobject', 'bacnetreadproperty', 'bacnetreadpropconditional', 'bacnetreadpropmultiple', 'bacnetwriteproperty', 'bacnetwritepropmultiple', 'bacnetdevicecommcontrol', 'bacnetconfirmedprivatexfer', 'bacnetconfirmedtextmessage', 'bacnetreinitializedevice', 'bacnetvtopen', 'bacnetvtclose', 'bacnetvtdata', 'bacnetauthenticate', 'bacnetrequestkey', 'bacnetreadrange', 'bacnetlifesafetyoperation', 'bacnetsubscribecovproperty', 'bacnetgeteventinformation', 'baiduhi', 'baiduhibase', 'baiduhiaudiovideo', 'baiduhifiletransfer', 'baiduhigames', 'bebo', 'bebomail', 'bebobase', 'beboposting', 'bitbucket', 'bitbucketbase', 'bitbucketuploading']
I believe this solves your problem:
new_dict = {}
for i in list1:
new_dict[i] = []
for j in list2:
if i in j:
new_dict[i].append(j)
Use a combined dict/list comprehension (it is shorter, but has worse readability):
new_dict = {key:[val for val in list2 if key in val and not key == val] for key in list1 if key in list2}
On my machine I get the following output:
{'assembla': ['assemblabase', 'assemblauploading'], 'bitbucket': ['bitbucketbase', 'bitbucketuploading']}
Updated with your more precise problem description. Just added a second condition within the list comprehension.
Use zip to create dict out to two list
a=[1,2]
b=["a","b"]
c=zip(a,b)
c=dict(c)

Python3: Adding two sets of dictionaries into new format

I have two dictionaries,
MaleDict = {'Jason':[(2014, 394),(2013, 350)...],
'Stephanie':[(2014, 3), (2013, 21),..]....}
FemaleDict = {'Jason':[(2014, 56),(2013, 23)...],
'Stephanie':[(2014, 335), (2013, 217),..]....}
I am attempting to add them so that
CompleteDict = {'Jason':[(2014, 394, 56),(2013, 350, 23)...],
'Stephanie':[(2014, 3, 335), (2013, 21, 217),..]....}
I have created a list comprehension that completes the task when the each dictionary has that year present. However, I need the output to present even if the year is not present in one of the MaleDict or FemaleDict. For example, if one year was not in the MaleDict the code would read ...'Stephanie':[....., (1999, 0, 389), ....]...
my list comprehensions are
for name_key in name_keys:
for year_key in year_keys:
[BaseDict[name_key].append((year_key, a[1], b[1])) for a in MaleDict[name_key] for b in FemaleDict[name_key] if (year_key == a[0] == b[0])]
#This is where I am stuck. My list comprehensions dont work when there is no value for a specific year
[BaseDict[name_key].append((year_key, a[1], 0)) for a in MaleDict[name_key] for b in FemaleDict[name_key] if (year_key == a[0] != b[0])]
[BaseDict[name_key].append((year_key, 0, b[1])) for a in MaleDict[name_key] for b in FemaleDict[name_key] if (year_key != a[0] == b[0])]
print(BaseDict)
If your data format is not set in stone, i would consider using a defaultdict from collections:
Instead of [(2014, 394),(2013, 350)...]
use collections.defaultdict(int, {2014: 394, 2013: 350}) etc.
Then you can use
for name_key in name_keys:
for year_key in year_keys:
CompleteDict[name_key].update([FemaleDict[year_key], MaleDict[year_key]])
CompleteDict['Stephanie'][1999] will then be [0, 389]

How to select based on a partial string match in Mathematica

Say I have a matrix that looks something like this:
{{foobar, 77},{faabar, 81},{foobur, 22},{faabaa, 8},
{faabian, 88},{foobar, 27}, {fiijii, 52}}
and a list like this:
{foo, faa}
Now I would like to add up the numbers for each line in the matrix based on the partial match of the strings in the list so that I end up with this:
{{foo, 126},{faa, 177}}
I assume I need to map a Select command, but I am not quite sure how to do that and match only the partial string. Can anybody help me? Now my real matrix is around 1.5 million lines so something that isn't too slow would be of added value.
Here is a starting point:
data={{"foobar",77},{"faabar",81},{"foobur",22},{"faabaa",8},{"faabian",88},{"foobar",27},{"fiijii",52}};
{str,vals}=Transpose[data];
vals=Developer`ToPackedArray[vals];
findValPos[str_List,strPat_String]:=
Flatten[Developer`ToPackedArray[
Position[StringPosition[str,strPat],Except[{}],{1},Heads->False]]]
Total[vals[[findValPos[str,"faa"]]]]
Here is yet another approach. It is reasonably fast, and also concise.
data =
{{"foobar", 77},
{"faabar", 81},
{"foobur", 22},
{"faabaa", 8},
{"faabian", 88},
{"foobar", 27},
{"fiijii", 52}};
match = {"foo", "faa"};
f = {#2, Tr # Pick[#[[All, 2]], StringMatchQ[#[[All, 1]], #2 <> "*"]]} &;
f[data, #]& /# match
{{"foo", 126}, {"faa", 177}}
You can use ruebenko's pre-processing for greater speed.
This is about twice as fast as his method on my system:
{str, vals} = Transpose[data];
vals = Developer`ToPackedArray[vals];
f2 = {#, Tr # Pick[vals, StringMatchQ[str, "*" <> # <> "*"]]} &;
f2 /# match
Notice that in this version I test substrings that are not at the beginning, to match ruebenko's output. If you want to only match at the beginning of strings, which is what I assumed in the first function, it will be faster still.
make data
mat = {{"foobar", 77},
{"faabar", 81},
{"foobur", 22},
{"faabaa", 8},
{"faabian", 88},
{"foobar", 27},
{"fiijii", 52}};
lst = {"foo", "faa"};
now select
r1 = Select[mat, StringMatchQ[lst[[1]], StringTake[#[[1]], 3]] &];
r2 = Select[mat, StringMatchQ[lst[[2]], StringTake[#[[1]], 3]] &];
{{lst[[1]], Total#r1[[All, 2]]}, {lst[[2]], Total#r2[[All, 2]]}}
gives
{{"foo", 126}, {"faa", 177}}
I'll try to make it more functional/general if I can...
edit(1)
This below makes it more general. (using same data as above):
foo[mat_, lst_] := Select[mat, StringMatchQ[lst, StringTake[#[[1]], 3]] &]
r = Map[foo[mat, #] &, lst];
MapThread[ {#1, Total[#2[[All, 2]]]} &, {lst, r}]
gives
{{"foo", 126}, {"faa", 177}}
So now same code above will work if lst was changed to 3 items instead of 2:
lst = {"foo", "faa", "fii"};
How about:
list = {{"foobar", 77}, {"faabar", 81}, {"foobur", 22}, {"faabaa",
8}, {"faabian", 88}, {"foobar", 27}, {"fiijii", 52}};
t = StringTake[#[[1]], 3] &;
{t[#[[1]]], Total[#[[All, 2]]]} & /# SplitBy[SortBy[list, t], t]
{{"faa", 177}, {"fii", 52}, {"foo", 126}}
I am sure I have read a post, maybe here, in which someone described a function that effectively combined sorting and splitting but I cannot remember it. Maybe someone else can add a comment if they know of it.
Edit
ok must be bedtime -- how could I forget Gatherby
{t[#[[1]]], Total[#[[All, 2]]]} & /# GatherBy[list, t]
{{"foo", 126}, {"faa", 177}, {"fii", 52}}
Note that for a dummy list of 1.4 million pairs this took a couple of seconds so not exactly a super fast method.

Resources