Fill a dictionnary from a list - python-3.x

Dears,
Your support please to have the below target output..
The input is a list in which the number whith four digits (exp : '1368', , '1568', '1768') should b the key of output dictionary, and the number with one digit which follow the 4 digits numbers should be the values of those keys like below.
exp :
INPUT :
['1368', '1', '1368', '3', '1568', '1', '1568', '3', '1568', '2', '1768', '3', '1768', '2', '2368', '1', '2368', '3', '2368', '2']
OUTPUT
{'1368' :['1', '3'], '1568' :['1', '3','2'], '1768' :['3','2'], '2368' :['1','3','2'] }
/////////////////////////////////////////////////////

try this:
output = {}
for key in iterator:=iter(input):
value = next(iterator)
output.setdefault(key, []).append(value)
But I apologize - this is a "pythonism" - as we in Python tend to avoid having to deal with explicit indexes for sequences. There is no harm in the more readable:
output = {}
for index in range(0, len(input), 2):
key, value = input[i], input[i+1]
output.setdefault(key, []).append(value)
The "setdefault" method on the other hand is a valid "pythonism" and is equivalent to "if this key already exists in the dicionary, return it, otherwise, set it to this new value (the second argument), and return it΅ - and it avoids the need for an "if" statement and an additional line.

Related

Number from a string of numbers-prolog

I would like to get a number within a string like
1100010 I would like to get the last two digits
How would I do that If I dunno the the length of the given String
forFun("",0).
forFun(Str,N) :- Str1 is Str - 1,
forFun(Str1,N1),
N is N1 + 1.
is that a possible code ?
First (unfortunately) we need to agree what we mean by "string". For many purposes the best and most portable representation is a list of "chars" (one-character atoms), though your Prolog might need to be told that this is really the representation you want:
?- set_prolog_flag(double_quotes, chars).
true.
Now, for example:
?- Number = "12345".
Number = ['1', '2', '3', '4', '5'].
To get the last two elements of a list, you can use the widely supported (though not standard) append/3 predicate. You can ask Prolog a question that amounts to "are there some list _Prefix (that I do not care about) and a two-element list LastDigits that, appended together, are equal to my Number?".
?- Number = "12345", LastDigits = [X, Y], append(_Prefix, LastDigits, Number).
Number = ['1', '2', '3', '4', '5'],
LastDigits = ['4', '5'],
X = '4',
Y = '5',
_Prefix = ['1', '2', '3'] ;
false.
The last two digits of this number are ['4', '5'].

Split '000111010010111' into ['000','111','0',1','00','1','0','111'] [duplicate]

This question already has answers here:
Splitting a string with repeated characters into a list
(4 answers)
Closed 2 years ago.
Is there some concise way to split up a string of 0s and 1s into the homogeneous, contiguous segments of all 0s and all 1s? Example in the title.
I can of course do it with a nested loop, conditionals, and the .count() method, but this seems like something there'd be a library function for. I'm just not sure how to search for it if there is.
Yes you can using itertools.groupby
from itertools import groupby
a = "000111010010111"
result = ["".join(list(group)) for key, group in groupby(a)]
What happened? We used itertools.groupby to group consecutive terms. A new group is created every time the key element changes (which is when a 0 turns into a 1 or a 1 turns into a 0 in your example). The inner lists are then joined to arrive at your desired output.
Output:
['000', '111', '0', '1', '00', '1', '0', '111']
This will work for any string (not just 1s and 0s) and will group items together based on their consecutive appearances.
This is a quick way of doing it with a generator function, easy to read and understand no cleverness involved.
def split_me(s):
temp=s[0]
last=s[0]
for l in s[1:]:
if l==last:
temp+=l
else:
yield temp
temp=l
last=l
yield temp
print(list(split_me('000111010010111')))
From the docs for re.split:
If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list
s = '000111010010111'
list(filter(None, re.split('(0+)', s)))
# ['000', '111', '0', '1', '00', '1', '0', '111']
s2 = '111110110110'
list(filter(None, re.split('(0+)', s)))
# ['11111', '0', '11', '0', '11', '0']
The filter removes empty groups at the beginning or end of the list

Replace a specific character at a specific position without using loops - Python

I am trying to replace a specific character at a specific position in a string.
This need to be accomplished without for loop and use of functions.
Here is an example - need to replace 5th character with x
s = "0123456789012345689"
Output needs to be - "01234x67890x23456x89"
I have tried replace(), split() but may be I am not using them in correct context. The string could be n characters long so I can't hardcode where I get the specific position and break them down in substrings. String are supposed to be immutable in python so are there any other alternatives?
Any help would be appreciated. Thanks.
I guess, if you strictly want to avoid for loops, the easiest way is converting to a list, replacing items, and then converting back.
This would be:
s = "0123456789012345689"
lst = list(s) # result: ['0', '1', '2', ..., '9']
lst[0:-1:5] = ["x"]*len(lst[0:-1:5])
Result then is:
In [43]: lst
Out[43]:
['x',
'1',
'2',
'3',
'4',
'x',
'6',
'7',
'8',
'9',
'x',
'1',
'2',
'3',
'4',
'x',
'6',
'8',
'9']
For getting it back to string you would simply use a join:
In [44]: "".join(lst)
Out[44]: 'x1234x6789x1234x689
The part lst[0:-1:5] select every 5th element in the list, beginning with the very first entry, denonted by 0:. If you want it to start at the 5th element, then simply do lst[5:-1:5]. The -1 part means "until the end", the last :5 stands for "every fifth".
Assigning values with ["x"]*len(lst[0:-1:5]) is needed, since "x" here would try to assign a single value to a slice of the original list with the length len(lst[0:-1:5]), because this is exactly how many items we selected in the first place.
EDIT:
Giving it a second look the expected outcome is actually to change every 6th character, not every 5th (while preserving 5 characters in between the changed ones from the original string).
One would then, of course, need to adjust the slicing to select every 6th character:
lst[5:-1:6] = ["x"]*len(lst[5:-1:6])
^ ^
Result:
In [12]: "".join(lst)
Out[12]: '01234x67890x23456x9'
Every sixth character now is being replaced, while preserving the 5 ones in between from the original string.
My solution to this would be this:
def replace_position(message, replacement, n):
lis = list(message) # get a list of all characters.
lis.pop(n) # delete the chosen character from the list.
lis.insert(n, replacement) # replace it at the given position.
return ''.join(lis)
Example use:
>>> a = 'Hello world, the 6th character is an x!'
>>> replace_postion(a, 'x', 6)
'Hello xorld, the 6th character is an x!'
However, this only gets the first one in that position. In order to do that, this is what I would do:
def replace_position(message, replacement, n):
lis = list(message)
for i in range(n, len(message), n + 1):
lis.pop(i)
lis.insert(i, replacement)
return ''.join(lis)
The only difference is that we are now iterating over the entire message, and replacing each of them as we go. Similar use:
>>> a = 'Hello world, every 6th character is an x!'
>>> replace_position(a, 'x', 6)
'Hello xorld, xvery 6xh charxcter ix an x!'
Hope this helps.
Try
s = "01234567890123456789012345"
pieces = []
for i in range((len(s)-1)//5):
pieces.append(s[i*6:i*6+5])
result = 'x'.join(pieces)
assert(result == '01234x67890x23456x89012x45')
We iterator over every window of six characters in the string, and then collect the first five characters in each window. We then join all of the windows together, using the string x as a separator.
To avoid using loops, you can convert the above into a list comprehension. I'll leave this step for you to complete.

Going over a list to find which if any items repeat more than X times, then returning those items

I have a list:
my_list = ['2', '5', '7', '7', '5']
I need to be able to check if any item repeats X time in the list, and if so - which one(s). For instance, I'd like to check if any (and which) items repeat (2) times in the list above, in which case I would expect:
5, 7 # this can be in the form of a list, strings, or anything else.
What I have tried:
After looking over some previous posts on StackExchange, I first went ahead and used collections-counter (not sure if this is a good approach), like so:
repetition = collections.Counter(my_list)
What this returns is a dictionary, like so:
{'5': 2, '7': 2, '2': 1}
Now I still need to check which item(s) repeat twice. After some more searching, I ended up with this:
def any(dict):
repeating = []
for element in dict.values():
if element == 2:
(...)
I'm uncertain however of how to continue with thise code. Seems like I can only get the number of repetitions, in this '2' (ie. the value from the dictionary), but am unable to figure out a simple way for getting the Keys which have a value of 2.
Is there an easy way to do it? Or should I try a different approach?
Thank you.
You need to loop over the items of the dictionary so you have both the key and the value:
repeating = [key for key, value in repetition.items() if value >= 2]
I used a list comprehension here to do the looping; all keys that have a value of 2 or higher are selected.
Demo:
>>> from collections import Counter
>>> my_list = ['2', '5', '7', '7', '5']
>>> repetition = Counter(my_list)
>>> [key for key, value in repetition.items() if value >= 2]
['5', '7']

I am trying to initialize a matrix, but get the same row repeated

I am trying to initialize a matrix of a list of lists of characters.
aRow = [ '0', '0','0' ]
aGrid = [ aRow, aRow, aRow ]
After it appeared like one row repeated three times, I tried modifying the rows as follows and printing the result:
aGrid[1][0] = '1'
aGrid[2][0] = '2'
print( aGrid )
It looks like I am getting the third row three times.
[['2', '0', '0'], ['2', '0', '0'], ['2', '0', '0']]
Why?
In python, when you assign values you're really assigning references to the values. So this statement creates a list with the value ['0', '0', '0'] and assigns a reference to that value to aRow:
aRow = [ '0', '0','0' ]
And so this statement then creates a list with three references to the same list:
aGrid = [ aRow, aRow, aRow ]
In Python, lists are mutable values, so changes to the underlying value are reflected by all references to that value. So:
aGrid[1][0] = '1'
and:
aGrid[2][0] = '2'
Both change the first element of the underlying list that all three references in aGrid are referencing, and so the last change is the one you'll see.
Because you are. You need to copy the object if you want the contents to be different.
aGrid = [aRow, aRow[:], aRow[:]]

Resources