I am writing logic to compare a few values.
I have three lists of values and one rule list
new_values = [1,0,0,0,1,1]
old_1 = [1,1,1,0,0,1]
old_2 = [1,0,1,0,1,1]
# when a is correct #when b is correct # if both are correct # if both are wrong
rules = ['a', 'b', 'combine', 'leave']
What I am looking for is, compare new_values to old_1 and old_2 values based on that select rule from rules list.
something like this:
def logic(new_values, old_values, rules):
rules_result = []
for new_value, old_value_1, old_value_2 in zip(new_values, old_values[0], old_values[1]):
if new_value == old_value_1 and new_value == old_value_2:
# if both are correct
rules_result.append(rules[2])
elif new_value == old_value_1:
# if a is correct
rules_result.append(rules[0])
elif new_value == old_value_2:
# if b is correct
rules_result.append(rules[1])
elif new_value!= old_value_1 and new_value!= old_value_2:
# if both are wrong
rules_result.append(rules[3])
return rules_result
Running this code with one rule list gives me this result :
logic(new_values, [old_1, old_2], rules)
output
['combine', 'b', 'leave', 'combine', 'b', 'combine']
I am facing issue to make this code dynamic if I have to compare more than two old values list, let say If I have three lists of old values and then my rule list will expand for each combination
new_values = [1,0,0,0,1,1]
old_1 = [1,1,1,0,0,1]
old_2 = [1,0,1,0,1,1]
old_3 = [0,0,0,1,1,1]
# when a is correct #when b is correct # if a and b are correct # if a and c are correct #if b and c are correct' #if all three are correct # if all three are wrong
rules = ['a', 'b', 'combine a_b', 'select c', 'combine b_c', 'select a', 'combine']
I am getting rules and values from a different function, I am looking for a rule selection function, where pass the list of old values ( example 2,3,4 list ) with new value and rule list, then dynamically compare each old list with new value list and select the rule from rule list.
How to make logic function dynamic to work on more than two old list values?
This problem could be solved easily if you use the concept of truth table. Your rules list defines the outcome for some boolean values. It doesn't consist of 1's and 0's so it can't be expressed by truth functions like and, or, xor but it's not a problem. You can simply rearrange your list by considering the order in the truth table:
# for 2 boolean variables, there are 2 ^ 2 = 4 possibilities
# ab ab ab ab
# 00 01 10 11
rules = ["leave", "b", "a", "combine"]
You can also turn this into a dict so you don't need to comment them to remember which one is what (and as a bonus, it will look like a truth table :)):
# ab
rules = {"00": "leave",
"01": "b",
"10": "a",
"11": "combine"}
Now, define a function to get the related key value for your boolean variables:
def get_rule_key(reference, values):
""" compares all the values against reference and returns a string for the result"""
return "".join(str(int(value == reference)) for value in values)
And your logic function will be simply this:
def logic(new_values, old_values, rules):
rules_result = []
for new_value, *old_values in zip(new_values, *old_values):
key = get_rule_key(new_value, old_values)
rules_result.append(rules.get(key))
return rules_result
print(logic(new_values, [old_1, old_2], rules))
# ['combine', 'b', 'leave', 'combine', 'b', 'combine']
For triples update your rules accordingly:
# for 3 boolean variables, there are 2 ^ 3 = 8 possibilities
# abc
rules = { "000": "combine",
# "001": Not defined in your rules,
"010": "b",
"011": "combine b_c",
"100": "a",
"101": "select c",
"110": "combine a_b"}
"111": "select a"}
print(logic(new_values, [old_1, old_2, old_3], rules))
# ['combine a_b', 'combine b_c', None, 'combine a_b', 'combine b_c', 'select a']
Notes:
None appears in the output because your rules doesn't define what is the output for "001" and dict.get returns None by default.
If you want to use a list to define the rules you have to define all the rules in order and convert the result of get_rule_key to an integer: "011" -> 3. You can manage this with int(x, base=2).
With unknown inputs it will be difficult to get this labels you specify.
It would be easy to map which ouf the old values corresponds to the same new value (positionally speaking). You can use a generic test function that gets a "new" value and all "old" values on that position, map the old values to 'a'... and return which ones correlate:
new_values = [1,0,0,0,1,1]
old_1 = [1,1,1,0,0,1]
old_2 = [1,0,1,0,1,1]
old_3 = [0,0,0,1,1,1]
old_4 = [0,0,0,1,1,1]
old_5 = [0,0,0,1,1,1]
def test(args):
nv, remain = args[0], list(args[1:])
start = ord("a")
# create dict from letter to its corresponding value
rv = {chr(start + i):v for i,v in enumerate(remain)}
# return tuples of the input and the matching outputs
return ((nv,remain), [k for k,v in rv.items() if v == nv])
rv = []
for values in zip(new_values, old_1, old_2, old_3, old_4, old_5):
rv.append(test(values))
print(*rv,sep="\n")
print([b for a,b in rv])
Output (manually spaced out):
# nv old_1 old_2 old_3 old_4 old_5
# a b c d e
((1, [ 1, 1, 0, 0, 0]), ['a', 'b'])
((0, [ 1, 0, 0, 0, 0]), ['b', 'c', 'd', 'e'])
((0, [ 1, 1, 0, 0, 0]), ['c', 'd', 'e'])
((0, [ 0, 0, 1, 1, 1]), ['a', 'b'])
((1, [ 0, 1, 1, 1, 1]), ['b', 'c', 'd', 'e'])
((1, [ 1, 1, 1, 1, 1]), ['a', 'b', 'c', 'd', 'e'])
[['a', 'b'], ['b', 'c', 'd', 'e'], ['c', 'd', 'e'], ['a', 'b'],
['b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']]
You could then map the joined results to some output:
# mapping needs completion - you'll need to hardcode that
# but if you consider inputs up to 5 old values, you need to specify those
# combinations that can happen for 5 as 4,3,2 are automagically included
# iif you omit "all of them" as result.
mapper = {"a": "only a", "ab": "a and b", "ac":"a and c", "abcde": "all of them",
# complete to your statisfaction on your own}
for inp, outp in rv:
result = ''.join(outp)
print(mapper.get(result , f"->'{result}' not mapped!"))
to get an output of:
a and b
->'bcde' not mapped!
->'cde' not mapped!
a and b
->'bcde' not mapped!
all of them
Related
This problem is similar to another where I learned How to Create Nested Dictionary in Python with 3 lists
How can I achieve an output such from 3 lists that takes the following output form
a = ['A', 'B', 'C', 'D']
b = [1,2,3,4]
c = ['N1', 'N2', 'N3', N4]
output = [{'A': {'N1':1}}, {'B':{'N2':2}}, {'C':{'N3':3}}, {'D':{'N4':4}}]
The output is different than on the posted link.
If I could describe this I would say it is a dictionary where 'N#' are the keywords for the values 1-4, and in turn those dictionaries have keyword 'A'-'D', which all seem to be dictionaries insided some top level keyword not shown under which they all are the elements of that master keyword.
I used this line of code which provided an output. These are different values than I'm using, but the point is this doesn't have as many curly brackets or the square brackets at the edges
d = {k: {x: y} for k, x, y in zip(a, b, c)}
# output: {'A':{'1' :'9'} , 'B':{'2':'8'}, 'C':{'3':'7'} , 'D':{'4':'6'}}
So I've explained what I think it means but I'm not sure how to proceed. I tried doing something like
d = {w:{k:{x:y}}for w,k,x,y in zip(sound, a, b, c)}
where 'sound' is a list of the same element value but that just prints out the 4th things on the list. Any help to clear this up would be much appreciated. Thanks.
Use a list comprehension. Iterate over the zipped lists and create the nested dictionaries:
a = ['A', 'B', 'C', 'D']
b = [1, 2, 3, 4]
c = ['N1', 'N2', 'N3', 'N4']
>>> [{k1: {k2: v}} for k1, v, k2 in zip(a, b, c)]
[{'A': {'N1': 1}}, {'B': {'N2': 2}}, {'C': {'N3': 3}}, {'D': {'N4': 4}}]
The dict comprehension is good by #mhawke, but let me add a more naive solution that may need to understand how to implement this type of nested Dictionary:
a = ['A', 'B', 'C', 'D']
b = [1, 2, 3, 4]
c = ['N1', 'N2', 'N3', 'N4']
output = [{'A': {'N1':1}}, {'B':{'N2':2}}, {'C':{'N3':3}}, {'D':{'N4':4}}]
def create_nested(a, b, c):
result = []
for i in range(len(a)):
parent = {}
child = {c[i]: b[i]}
parent.setdefault(a[i], child)
result.append(parent)
return result
result = create_nested(a, b, c)
print(result)
assert result == output
Using enumerate
def create_nested(a, b, c):
result = []
for idx, value in enumerate(a):
child = {c[idx]: b[idx]}
parent = {a[idx]: child}
result.append(parent)
return result
Shorter form
for idx, value in enumerate(a):
parent = {a[idx]: {c[idx]: b[idx]}}
result.append(parent)
return result
Enumerate
So i try to make X number of lists where X is the number of nargs provided in my program.
Example: python program.py --payloads file1 file2 file3 file4... up to 20 nargs.
This gives me a list of: payloads_sets = [file1, file2, file3, file4] (takes up to 20 files)
Now, here is the tricky part where i got stuck. I need to read from each file and iterate through each payload in the file simultaneously to set it in the request I'll make for every payload in the files.
TL;DR: There is a different payload set for each defined position (up to a
maximum of 20). The attack iterates through all payload sets simultaneously and places one payload into each defined position.
For example:
Payload_set_1 = [1, 2, 3,...]
Payload_set_2 = [a, b, c,...]
Payload_set_3 = [x, y, z,...]
data = {var_a: marked_position_1,
var_b: marked_position_2,
var_c: marked_position_3}
The desired sent requests:
for loop of something: send this:
data = {var_a: 1, var_b: 'a', var_c: 'x'}
data = {var_a: 2, var_b: 'b', var_c: 'y'}
data = {var_a: 3, var_b: 'c', var_c: 'z'}
Hope someone can clarify that for me or suggest another method to make it work.
Long story short, I need to replicate what BurpSuite's Intruder Pitchfork attack does.
You can use the zip function with destructuring in order to do this:
var_names = ["var_a", "var_b", "var_c"]
values = [
[1, 2, 3],
["a", "b", "c"],
["x", "y", "z"]
]
# iterate through the values together
for cur_values in zip(*values):
# match the values with their name
named_values = zip(var_names, cur_values)
# use the iterator of tuple constructor to make a dict
value_dict = dict(named_values)
print(value_dict)
Output:
{'var_a': 1, 'var_b': 'a', 'var_c': 'x'}
{'var_a': 2, 'var_b': 'b', 'var_c': 'y'}
{'var_a': 3, 'var_b': 'c', 'var_c': 'z'}
I want to separate each (key, value) pair from a dictionary and want to call each value by its key name.
I have two lists,
1. ListA = [1, 2, 3, 4, 5]
2. ListB = ['A', 'B', 'C', 'D', 'E']
Now I have created a dictionary like this,
Dict = {1: 'A', 2: 'B', 3: 'C', 4: 'D', 5: 'E'}
So, now if I want to see value for each key, I have to type:
Dict[key].
Now I expect my result to be like:
If I ask for the value of each key, I have to just type key not Dict[key]
and it should give me the answer.
Typing 1 should give A.
Typing 2 should give B.
You can somehow do like this but you if you can simply access below is not a very good idea honestly. You can set key as attribute of an object.
But it wont work for the dictionary you have my Input Dictionary is {"key1":"Apple"}
class MyDict:
def __init__(self,input_dict):
for key,value in input_dict.items():
setattr(self,key,value) #setting key as attribute
obj = MyDict({"key1":"Apple"}) #new instance
print(obj.key1) # this will print Apple
But still it wont work like obj.1 better not to mess it.
If you want to loop over dictionary values, you can use Dict.values():
for v in Dict.values():
print(v)
# > 'A'
# > 'B'
# ...
Inside a while true loop, keep popping items from your lists until you run into an IndexError like this:
ListA = [1, 2, 3]
ListB = ['A', 'B', 'C']
DictC = {}
while True:
try:
DictC[ListA.pop(0)] = ListB.pop(0)
except IndexError:
break
print(DictC)
I have a list of lists as follows
[
['a', 1],
['b',2],
['c',1],
['a', 2],
['c', 5]
]
I want to normalize this list in such a way that for every, 'a', 'b', 'c' etc, I have only one unique entry in the list, and for every duplicate list, the second value which is the quantity is added so that I get something like:
[
['a', 3], # so since 'a' already existed the quantity is added 1 + 2 becomes 3
['b',2],
['c',6] # similarly for 'c' it becomes 1 + 5 = 6
]
How to do this with Python ?
I'd suggest use collections.defaultdict() like below:
from collections import defaultdict
l = [
['a', 1],
['b',2],
['c',1],
['a', 2],
['c', 5]
]
d = defaultdict(int)
for key, value in l:
d[key] += value
print(d.items())
Output:
dict_items([('b', 2), ('a', 3), ('c', 6)])
Also you can use a try...expect instead of collections.defaultdict()...if you'd like:
d = {}
for key, value in l:
try:
d[key] += value
except KeyError:
d[key] = value
Also, you can try if...else:
d = {}
for key, value in l:
if key in d:
d[key] += value
else:
d[key] = value
here is a long way to do it, but returns a list, not a data object
def normalizelist(inp):
out=[]
for key,count in inp:
exist=0
for place, val in enumerate(out):
if (key==val[0]):
out[place][1]+=count
exist=1 #found it, so don't need to make it
break #no need to go further
if (exist==0): #didn't find it, therefor it needs to be added
out.append([key,count])
return out
hopefully that helps!
I have a defaultdict that looks like this:
d = { 'ID_001': ['A', 'A_part1', 'A_part2'],
'ID_002': ['A', 'A_part3'],
'ID_003': ['B', 'B_part1', 'B_part2', 'A', 'A_part4'],
'ID_004': ['C', 'C_part1', 'A', 'A_part5', 'B', 'B_part3']
}
Before I go any further, I have to say that A_part1 isn't the actual string -- the strings are really a bunch of alphanumeric characters; I represented it as such to show that A_part1 is text that is associated with A, if you see what I mean.)
Standing back and looking at it, what I really have is a dict where the values have their own key/value relationship, but that relationship exists only in the order they appear in, in the list.
I am attempting to end up with something like this:
['ID_001 A A_part1, A_part2',
'ID_002 A A_part3',
'ID_003 B B_part1 B_part2',
'ID_003 A A_part4',
'ID_004 C C_part1',
'ID_004 A A_part5',
'ID_004 B B_part3']
I have made a variety of attempts; I keep wanting to run through the dict's value, making note of the character in the first position (eg, the A), and collect values until I find a B or a C, then stop collecting. Then append what I have to a list that I have declared elsewhere. Ad nauseum.
I'm running into all sorts of problems, not the least of which is bloated code. I'm missing the ability to iterate through the value in a clean way. Invariably, I seem to run into index errors.
If anyone has any ideas/philosophy/comments I'd be grateful.
What about something like:
d = { 'ID_001': ['A', 'A_part1', 'A_part2'],
'ID_002': ['A', 'A_part3'],
'ID_003': ['B', 'B_part1', 'B_part2', 'A', 'A_part4'],
'ID_004': ['C', 'C_part1', 'A', 'A_part5', 'B', 'B_part3']
}
def is_key(s):
return s in ['A','B','C']
out = {}
for (k,v) in d.iteritems():
key = None
for e in v:
if is_key(e): key = e
else:
out_key = (k,key)
out[out_key] = out.get(out_key, []) + [e]
which generates:
{('ID_001', 'A'): ['A_part1', 'A_part2'],
('ID_002', 'A'): ['A_part3'],
('ID_003', 'A'): ['A_part4'],
('ID_003', 'B'): ['B_part1', 'B_part2'],
('ID_004', 'A'): ['A_part5'],
('ID_004', 'B'): ['B_part3'],
('ID_004', 'C'): ['C_part1']}
It's important that you update the is_key function to match your actual input.
Also, the variable names are far from optimal, but I'm not really sure what you're doing -- you should be able to (and should) give them more appropriate names.
May not be in the order you want, but no thanks for further headaches.
d = { 'ID_001': ['A', 'A_part1', 'A_part2'],
'ID_002': ['A', 'A_part3'],
'ID_003': ['B', 'B_part1', 'B_part2', 'A', 'A_part4'],
'ID_004': ['C', 'C_part1', 'A', 'A_part5', 'B', 'B_part3']
}
rst = []
for o in d:
t_d={}
for t_o in d[o]:
if not t_o[0] in t_d:
t_d[t_o[0]] = [t_o]
else: t_d[t_o[0]].append(t_o)
for t_o in t_d:
rst.append(' '.join([o,t_d[t_o][0],', '.join(t_d[t_o][1:])]))
print(rst)
https://ideone.com/FeBDLA
['ID_004 C C_part1', 'ID_004 A A_part5', 'ID_004 B B_part3', 'ID_003 A A_part4', 'ID_003 B B_part1, B_part2', 'ID_002 A A_part3', 'ID_001 A A_part1, A_part2']
Whenever you're trying to do something involving contiguous groups, you should think of itertools.groupby. You weren't very specific about what condition separates the groups, but if we take "the character in the first position" at face value:
from itertools import groupby
new_list = []
for key, sublist in sorted(d.items()):
for _, group in groupby(sublist, key=lambda x: x[0]):
new_list.append(' '.join([key] + list(group)))
produces
>>> for elem in new_list:
... print(elem)
...
ID_001 A A_part1 A_part2
ID_002 A A_part3
ID_003 B B_part1 B_part2
ID_003 A A_part4
ID_004 C C_part1
ID_004 A A_part5
ID_004 B B_part3