Python “triplet” dictionary?How to merge two dictionaries in a single expression?Calling an external command in PythonWhat are metaclasses in Python?How can I safely create a nested directory in Python?Does Python have a ternary conditional operator?How do I sort a dictionary by value?Add new keys to a dictionary?Check if a given key already exists in a dictionaryIterating over dictionaries using 'for' loopsDoes Python have a string 'contains' substring method?
Can solid acids and bases have pH values? If not, how are they classified as acids or bases?
Were there two appearances of Stan Lee?
What are the spoon bit of a spoon and fork bit of a fork called?
You look catfish vs You look like a catfish
Phrase for the opposite of "foolproof"
Was there a Viking Exchange as well as a Columbian one?
Corner spot where three faces meet
Can my Warlock be invisible and attack with its familiar?
Why was Germany not as successful as other Europeans in establishing overseas colonies?
Python: pythonic way to find last position in string that does not match regex
Why are the 2nd/3rd singular forms of present of « potere » irregular?
An uncommon variant of 写
Packing rectangles: Does rotation ever help?
How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?
Single Colour Mastermind Problem
What is a Recurrent Neural Network?
Subtleties of choosing the sequence of tenses in Russian
Lock in SQL Server and Oracle
Minimum value of 4 digit number divided by sum of its digits
gnu parallel how to use with ffmpeg
Binary Numbers Magic Trick
How to set the font color of quantity objects (Version 11.3 vs version 12)?
Confused by notation of atomic number Z and mass number A on periodic table of elements
Are Boeing 737-800’s grounded?
Python “triplet” dictionary?
How to merge two dictionaries in a single expression?Calling an external command in PythonWhat are metaclasses in Python?How can I safely create a nested directory in Python?Does Python have a ternary conditional operator?How do I sort a dictionary by value?Add new keys to a dictionary?Check if a given key already exists in a dictionaryIterating over dictionaries using 'for' loopsDoes Python have a string 'contains' substring method?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
If we have (a1, b1)
and (a2, b2)
it's easy to use a dictionary to store the correspondences:
dict[a1] = b1
dict[a2] = b2
And we can get (a1, b1)
and (a2, b2)
back no problem.
But, if we have (a1, b1, c1)
and (a2, b2, c2)
, is it possible to get something like:
dict[a1] = (b1, c1)
dict[b1] = (a1, c1)
Where we can use either a1
or b1
to get the triplet (a1, b1, c2)
back? Does that make sense? I'm not quite sure which datatype to use for this problem. The above would work but there would be duplicate data.
Basically, if I have a triplet, which data type could I use such that I can use either the first or second value to get the triplet back?
python
|
show 1 more comment
If we have (a1, b1)
and (a2, b2)
it's easy to use a dictionary to store the correspondences:
dict[a1] = b1
dict[a2] = b2
And we can get (a1, b1)
and (a2, b2)
back no problem.
But, if we have (a1, b1, c1)
and (a2, b2, c2)
, is it possible to get something like:
dict[a1] = (b1, c1)
dict[b1] = (a1, c1)
Where we can use either a1
or b1
to get the triplet (a1, b1, c2)
back? Does that make sense? I'm not quite sure which datatype to use for this problem. The above would work but there would be duplicate data.
Basically, if I have a triplet, which data type could I use such that I can use either the first or second value to get the triplet back?
python
1
You want to be able to recover the triplet from any of the elements?
– Olivier Melançon
3 hours ago
@OlivierMelançon For my specific problem, if I havea1
, I'd like to knowb1
andc1
. And if I only haveb1
, I'd need to knowa1
andc1
. But I'd never havec1
directly... If that makes sense.
– Justin
3 hours ago
1
perfect time to learn how to make your own data types. see docs.python.org/3/library/stdtypes.html#typesmapping
– user633183
3 hours ago
1
Quick hint: you would either need a custom mapping type (e.g. adict
subclass with__getitem__
overridden, at the very least) or you would need some custom container type that can wrap each item of your tuples and the tuples themselves such that they have the same__hash__
. I suspect you might have an X-Y problem though but hard to be sure.
– Iguananaut
3 hours ago
2
I think it's an interesting problem. The answers given below are the most obvious but if you wanted to completely avoid duplication you'd have to do some tricks with hashes. I have to say, while it's a neat idea, in 25 years of programming I have never needed a data structure quite like this which is why I suspect an X-Y problem, but who knows stranger things have happened.
– Iguananaut
3 hours ago
|
show 1 more comment
If we have (a1, b1)
and (a2, b2)
it's easy to use a dictionary to store the correspondences:
dict[a1] = b1
dict[a2] = b2
And we can get (a1, b1)
and (a2, b2)
back no problem.
But, if we have (a1, b1, c1)
and (a2, b2, c2)
, is it possible to get something like:
dict[a1] = (b1, c1)
dict[b1] = (a1, c1)
Where we can use either a1
or b1
to get the triplet (a1, b1, c2)
back? Does that make sense? I'm not quite sure which datatype to use for this problem. The above would work but there would be duplicate data.
Basically, if I have a triplet, which data type could I use such that I can use either the first or second value to get the triplet back?
python
If we have (a1, b1)
and (a2, b2)
it's easy to use a dictionary to store the correspondences:
dict[a1] = b1
dict[a2] = b2
And we can get (a1, b1)
and (a2, b2)
back no problem.
But, if we have (a1, b1, c1)
and (a2, b2, c2)
, is it possible to get something like:
dict[a1] = (b1, c1)
dict[b1] = (a1, c1)
Where we can use either a1
or b1
to get the triplet (a1, b1, c2)
back? Does that make sense? I'm not quite sure which datatype to use for this problem. The above would work but there would be duplicate data.
Basically, if I have a triplet, which data type could I use such that I can use either the first or second value to get the triplet back?
python
python
asked 3 hours ago
JustinJustin
3,26422549
3,26422549
1
You want to be able to recover the triplet from any of the elements?
– Olivier Melançon
3 hours ago
@OlivierMelançon For my specific problem, if I havea1
, I'd like to knowb1
andc1
. And if I only haveb1
, I'd need to knowa1
andc1
. But I'd never havec1
directly... If that makes sense.
– Justin
3 hours ago
1
perfect time to learn how to make your own data types. see docs.python.org/3/library/stdtypes.html#typesmapping
– user633183
3 hours ago
1
Quick hint: you would either need a custom mapping type (e.g. adict
subclass with__getitem__
overridden, at the very least) or you would need some custom container type that can wrap each item of your tuples and the tuples themselves such that they have the same__hash__
. I suspect you might have an X-Y problem though but hard to be sure.
– Iguananaut
3 hours ago
2
I think it's an interesting problem. The answers given below are the most obvious but if you wanted to completely avoid duplication you'd have to do some tricks with hashes. I have to say, while it's a neat idea, in 25 years of programming I have never needed a data structure quite like this which is why I suspect an X-Y problem, but who knows stranger things have happened.
– Iguananaut
3 hours ago
|
show 1 more comment
1
You want to be able to recover the triplet from any of the elements?
– Olivier Melançon
3 hours ago
@OlivierMelançon For my specific problem, if I havea1
, I'd like to knowb1
andc1
. And if I only haveb1
, I'd need to knowa1
andc1
. But I'd never havec1
directly... If that makes sense.
– Justin
3 hours ago
1
perfect time to learn how to make your own data types. see docs.python.org/3/library/stdtypes.html#typesmapping
– user633183
3 hours ago
1
Quick hint: you would either need a custom mapping type (e.g. adict
subclass with__getitem__
overridden, at the very least) or you would need some custom container type that can wrap each item of your tuples and the tuples themselves such that they have the same__hash__
. I suspect you might have an X-Y problem though but hard to be sure.
– Iguananaut
3 hours ago
2
I think it's an interesting problem. The answers given below are the most obvious but if you wanted to completely avoid duplication you'd have to do some tricks with hashes. I have to say, while it's a neat idea, in 25 years of programming I have never needed a data structure quite like this which is why I suspect an X-Y problem, but who knows stranger things have happened.
– Iguananaut
3 hours ago
1
1
You want to be able to recover the triplet from any of the elements?
– Olivier Melançon
3 hours ago
You want to be able to recover the triplet from any of the elements?
– Olivier Melançon
3 hours ago
@OlivierMelançon For my specific problem, if I have
a1
, I'd like to know b1
and c1
. And if I only have b1
, I'd need to know a1
and c1
. But I'd never have c1
directly... If that makes sense.– Justin
3 hours ago
@OlivierMelançon For my specific problem, if I have
a1
, I'd like to know b1
and c1
. And if I only have b1
, I'd need to know a1
and c1
. But I'd never have c1
directly... If that makes sense.– Justin
3 hours ago
1
1
perfect time to learn how to make your own data types. see docs.python.org/3/library/stdtypes.html#typesmapping
– user633183
3 hours ago
perfect time to learn how to make your own data types. see docs.python.org/3/library/stdtypes.html#typesmapping
– user633183
3 hours ago
1
1
Quick hint: you would either need a custom mapping type (e.g. a
dict
subclass with __getitem__
overridden, at the very least) or you would need some custom container type that can wrap each item of your tuples and the tuples themselves such that they have the same __hash__
. I suspect you might have an X-Y problem though but hard to be sure.– Iguananaut
3 hours ago
Quick hint: you would either need a custom mapping type (e.g. a
dict
subclass with __getitem__
overridden, at the very least) or you would need some custom container type that can wrap each item of your tuples and the tuples themselves such that they have the same __hash__
. I suspect you might have an X-Y problem though but hard to be sure.– Iguananaut
3 hours ago
2
2
I think it's an interesting problem. The answers given below are the most obvious but if you wanted to completely avoid duplication you'd have to do some tricks with hashes. I have to say, while it's a neat idea, in 25 years of programming I have never needed a data structure quite like this which is why I suspect an X-Y problem, but who knows stranger things have happened.
– Iguananaut
3 hours ago
I think it's an interesting problem. The answers given below are the most obvious but if you wanted to completely avoid duplication you'd have to do some tricks with hashes. I have to say, while it's a neat idea, in 25 years of programming I have never needed a data structure quite like this which is why I suspect an X-Y problem, but who knows stranger things have happened.
– Iguananaut
3 hours ago
|
show 1 more comment
4 Answers
4
active
oldest
votes
Solution
You can write your own mapping data-structure which allows to add
triples, or groups of any size, and recover the group with __getitem__
.
class GroupMap:
def __init__(self):
self.data =
def add(self, group):
for item in group:
self.data[item] = group
def __getitem__(self, item):
return self.data[item]
group = (1, 2, 3)
group_map = GroupMap()
group_map.add(group)
print(group_map[1]) # (1, 2, 3)
Notice that this GroupMap
can be used for groups of any size, not only triples.
The next step in the above would be to extend the class to avoid collisions according to the behaviour you want when a collision occurs.
Theory
You might wonder if there is a better way to represent groups of connected objects. The answer is not really.
Suppose you have a graph containing n vertices. Then for the graph to be connected, you must have at least n - 1 edges. In the above data-structure, I used n entry in the dict
, meaning the solution is nearly optimal.
Why not use n - 1 entries if it can be done? Because you would then need to traverse all your graph to recover the whole group. Thus using one more edge allows for O(1) lookup, which is a trade-off you probably want to take.
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
1
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
1
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
|
show 4 more comments
An alternative if you want to subclass dict
(to get all other methods associated with dict
like .get
and whatnot) and only get the other elements when asked (for some reason). You can make a new dictionary that is all your own
class TupleDict(dict):
def __setitem__(self, key, value):
assert isinstance(key, tuple)
for i, e in enumerate(key):
dict.__setitem__(self, e, key[:i] + key[i+1:] + (value,))
dict.__setitem__(self, value, key)
and then assign any key that is a tuple to a single value (not sure I like this syntax, but we can make it different or use a stand-alone method)
d = TriDict()
d[(1,2)] = 4
and you will have the result of __getitem__
return the rest of the tuple not present.
>>> print(d[1])
(2, 4)
>>> print(d[2])
(1, 4)
print(d[4])
>>> (1, 2)
add a comment |
Dictionaries can store key value pairs only.
You could make your own triplet dictionary however using operator overloading so that when you index with any member of the triplets you get back the other two, maybe something like this:
class trictionary:
def __init__(self):
self.data = []
def add(self, group):
self.data.append(group)
def __getitem__(self, key):
for group in data: #Find the set the key belongs to.
if key in group:
return tuple(group)
This avoids replicating the data and has the functionality you're looking for at the expense of performance. There may be a better way of doing the same.
1
I love "trictionary"
– modesitt
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
add a comment |
Building on Olivier Melançons answer, I came up with this - in case the position of the value in the tuple matters:
class GroupMap:
def __init__(self, data=None):
self.data =
if data:
self.add(data)
def add(self, data):
for idx, key in enumerate(data):
self.data.setdefault(idx, )[key] = data
def __getitem__(self, key):
# lookup in first index
return self.getby(0, key)
def getby(self, idx, key):
return self.data[idx].get(key)
data = ('a', 'b', 'c')
g = GroupMap(data)
more_data = ('b', 'a', 'z')
g.add(more_data)
assert g['a'] == data
assert g.getby(0, 'a') == data
assert g.getby(0, 'b') == more_data
assert g.getby(0, 'c') is None
assert g.getby(1, 'a') == more_data
assert g.getby(1, 'b') == data
assert g.getby(2, 'c') == data
assert g.getby(2, 'z') == more_data
assert id(data) == id(g['a']) == id(g.getby(1, 'b'))
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55892600%2fpython-triplet-dictionary%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Solution
You can write your own mapping data-structure which allows to add
triples, or groups of any size, and recover the group with __getitem__
.
class GroupMap:
def __init__(self):
self.data =
def add(self, group):
for item in group:
self.data[item] = group
def __getitem__(self, item):
return self.data[item]
group = (1, 2, 3)
group_map = GroupMap()
group_map.add(group)
print(group_map[1]) # (1, 2, 3)
Notice that this GroupMap
can be used for groups of any size, not only triples.
The next step in the above would be to extend the class to avoid collisions according to the behaviour you want when a collision occurs.
Theory
You might wonder if there is a better way to represent groups of connected objects. The answer is not really.
Suppose you have a graph containing n vertices. Then for the graph to be connected, you must have at least n - 1 edges. In the above data-structure, I used n entry in the dict
, meaning the solution is nearly optimal.
Why not use n - 1 entries if it can be done? Because you would then need to traverse all your graph to recover the whole group. Thus using one more edge allows for O(1) lookup, which is a trade-off you probably want to take.
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
1
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
1
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
|
show 4 more comments
Solution
You can write your own mapping data-structure which allows to add
triples, or groups of any size, and recover the group with __getitem__
.
class GroupMap:
def __init__(self):
self.data =
def add(self, group):
for item in group:
self.data[item] = group
def __getitem__(self, item):
return self.data[item]
group = (1, 2, 3)
group_map = GroupMap()
group_map.add(group)
print(group_map[1]) # (1, 2, 3)
Notice that this GroupMap
can be used for groups of any size, not only triples.
The next step in the above would be to extend the class to avoid collisions according to the behaviour you want when a collision occurs.
Theory
You might wonder if there is a better way to represent groups of connected objects. The answer is not really.
Suppose you have a graph containing n vertices. Then for the graph to be connected, you must have at least n - 1 edges. In the above data-structure, I used n entry in the dict
, meaning the solution is nearly optimal.
Why not use n - 1 entries if it can be done? Because you would then need to traverse all your graph to recover the whole group. Thus using one more edge allows for O(1) lookup, which is a trade-off you probably want to take.
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
1
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
1
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
|
show 4 more comments
Solution
You can write your own mapping data-structure which allows to add
triples, or groups of any size, and recover the group with __getitem__
.
class GroupMap:
def __init__(self):
self.data =
def add(self, group):
for item in group:
self.data[item] = group
def __getitem__(self, item):
return self.data[item]
group = (1, 2, 3)
group_map = GroupMap()
group_map.add(group)
print(group_map[1]) # (1, 2, 3)
Notice that this GroupMap
can be used for groups of any size, not only triples.
The next step in the above would be to extend the class to avoid collisions according to the behaviour you want when a collision occurs.
Theory
You might wonder if there is a better way to represent groups of connected objects. The answer is not really.
Suppose you have a graph containing n vertices. Then for the graph to be connected, you must have at least n - 1 edges. In the above data-structure, I used n entry in the dict
, meaning the solution is nearly optimal.
Why not use n - 1 entries if it can be done? Because you would then need to traverse all your graph to recover the whole group. Thus using one more edge allows for O(1) lookup, which is a trade-off you probably want to take.
Solution
You can write your own mapping data-structure which allows to add
triples, or groups of any size, and recover the group with __getitem__
.
class GroupMap:
def __init__(self):
self.data =
def add(self, group):
for item in group:
self.data[item] = group
def __getitem__(self, item):
return self.data[item]
group = (1, 2, 3)
group_map = GroupMap()
group_map.add(group)
print(group_map[1]) # (1, 2, 3)
Notice that this GroupMap
can be used for groups of any size, not only triples.
The next step in the above would be to extend the class to avoid collisions according to the behaviour you want when a collision occurs.
Theory
You might wonder if there is a better way to represent groups of connected objects. The answer is not really.
Suppose you have a graph containing n vertices. Then for the graph to be connected, you must have at least n - 1 edges. In the above data-structure, I used n entry in the dict
, meaning the solution is nearly optimal.
Why not use n - 1 entries if it can be done? Because you would then need to traverse all your graph to recover the whole group. Thus using one more edge allows for O(1) lookup, which is a trade-off you probably want to take.
edited 3 hours ago
answered 3 hours ago
Olivier MelançonOlivier Melançon
14.4k32142
14.4k32142
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
1
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
1
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
|
show 4 more comments
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
1
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
1
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
Wouldn't this still duplicate the information in the same way?
– GiraffeMan91
3 hours ago
1
1
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
@GiraffeMan91 Yes, but there is no other way. A connexion between two items must be stored one way of another. Another way to visualize this is that a graph of n items must have at least (n-1) vertices to be connected. Here I use two more than that, but this is to allow fast lookup.
– Olivier Melançon
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
Yea I understand I just wanted to be clear that we agreed. I thought the primary element of the question was to reduce duplication which I don't believe can be done either, I just thought your answer turned what the post already said they could do into a class with methods, which is written nicely, but I felt the post already explained they knew how to do what your answer provided and they were looking for other methods.
– GiraffeMan91
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
@GiraffeMan91 Fair point, I edited the answer to explain why we cannot do better than that.
– Olivier Melançon
3 hours ago
1
1
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
@GiraffeMan91 The problem I see with traversal is that it requires implementing some kind of graph data-structure which 1) slows down everything and 2) is a bit overly complex in my opinion for what we want to achieve.
– Olivier Melançon
3 hours ago
|
show 4 more comments
An alternative if you want to subclass dict
(to get all other methods associated with dict
like .get
and whatnot) and only get the other elements when asked (for some reason). You can make a new dictionary that is all your own
class TupleDict(dict):
def __setitem__(self, key, value):
assert isinstance(key, tuple)
for i, e in enumerate(key):
dict.__setitem__(self, e, key[:i] + key[i+1:] + (value,))
dict.__setitem__(self, value, key)
and then assign any key that is a tuple to a single value (not sure I like this syntax, but we can make it different or use a stand-alone method)
d = TriDict()
d[(1,2)] = 4
and you will have the result of __getitem__
return the rest of the tuple not present.
>>> print(d[1])
(2, 4)
>>> print(d[2])
(1, 4)
print(d[4])
>>> (1, 2)
add a comment |
An alternative if you want to subclass dict
(to get all other methods associated with dict
like .get
and whatnot) and only get the other elements when asked (for some reason). You can make a new dictionary that is all your own
class TupleDict(dict):
def __setitem__(self, key, value):
assert isinstance(key, tuple)
for i, e in enumerate(key):
dict.__setitem__(self, e, key[:i] + key[i+1:] + (value,))
dict.__setitem__(self, value, key)
and then assign any key that is a tuple to a single value (not sure I like this syntax, but we can make it different or use a stand-alone method)
d = TriDict()
d[(1,2)] = 4
and you will have the result of __getitem__
return the rest of the tuple not present.
>>> print(d[1])
(2, 4)
>>> print(d[2])
(1, 4)
print(d[4])
>>> (1, 2)
add a comment |
An alternative if you want to subclass dict
(to get all other methods associated with dict
like .get
and whatnot) and only get the other elements when asked (for some reason). You can make a new dictionary that is all your own
class TupleDict(dict):
def __setitem__(self, key, value):
assert isinstance(key, tuple)
for i, e in enumerate(key):
dict.__setitem__(self, e, key[:i] + key[i+1:] + (value,))
dict.__setitem__(self, value, key)
and then assign any key that is a tuple to a single value (not sure I like this syntax, but we can make it different or use a stand-alone method)
d = TriDict()
d[(1,2)] = 4
and you will have the result of __getitem__
return the rest of the tuple not present.
>>> print(d[1])
(2, 4)
>>> print(d[2])
(1, 4)
print(d[4])
>>> (1, 2)
An alternative if you want to subclass dict
(to get all other methods associated with dict
like .get
and whatnot) and only get the other elements when asked (for some reason). You can make a new dictionary that is all your own
class TupleDict(dict):
def __setitem__(self, key, value):
assert isinstance(key, tuple)
for i, e in enumerate(key):
dict.__setitem__(self, e, key[:i] + key[i+1:] + (value,))
dict.__setitem__(self, value, key)
and then assign any key that is a tuple to a single value (not sure I like this syntax, but we can make it different or use a stand-alone method)
d = TriDict()
d[(1,2)] = 4
and you will have the result of __getitem__
return the rest of the tuple not present.
>>> print(d[1])
(2, 4)
>>> print(d[2])
(1, 4)
print(d[4])
>>> (1, 2)
edited 3 hours ago
answered 3 hours ago
modesittmodesitt
3,03121745
3,03121745
add a comment |
add a comment |
Dictionaries can store key value pairs only.
You could make your own triplet dictionary however using operator overloading so that when you index with any member of the triplets you get back the other two, maybe something like this:
class trictionary:
def __init__(self):
self.data = []
def add(self, group):
self.data.append(group)
def __getitem__(self, key):
for group in data: #Find the set the key belongs to.
if key in group:
return tuple(group)
This avoids replicating the data and has the functionality you're looking for at the expense of performance. There may be a better way of doing the same.
1
I love "trictionary"
– modesitt
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
add a comment |
Dictionaries can store key value pairs only.
You could make your own triplet dictionary however using operator overloading so that when you index with any member of the triplets you get back the other two, maybe something like this:
class trictionary:
def __init__(self):
self.data = []
def add(self, group):
self.data.append(group)
def __getitem__(self, key):
for group in data: #Find the set the key belongs to.
if key in group:
return tuple(group)
This avoids replicating the data and has the functionality you're looking for at the expense of performance. There may be a better way of doing the same.
1
I love "trictionary"
– modesitt
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
add a comment |
Dictionaries can store key value pairs only.
You could make your own triplet dictionary however using operator overloading so that when you index with any member of the triplets you get back the other two, maybe something like this:
class trictionary:
def __init__(self):
self.data = []
def add(self, group):
self.data.append(group)
def __getitem__(self, key):
for group in data: #Find the set the key belongs to.
if key in group:
return tuple(group)
This avoids replicating the data and has the functionality you're looking for at the expense of performance. There may be a better way of doing the same.
Dictionaries can store key value pairs only.
You could make your own triplet dictionary however using operator overloading so that when you index with any member of the triplets you get back the other two, maybe something like this:
class trictionary:
def __init__(self):
self.data = []
def add(self, group):
self.data.append(group)
def __getitem__(self, key):
for group in data: #Find the set the key belongs to.
if key in group:
return tuple(group)
This avoids replicating the data and has the functionality you're looking for at the expense of performance. There may be a better way of doing the same.
answered 3 hours ago
Eden TrainorEden Trainor
246
246
1
I love "trictionary"
– modesitt
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
add a comment |
1
I love "trictionary"
– modesitt
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
1
1
I love "trictionary"
– modesitt
3 hours ago
I love "trictionary"
– modesitt
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
That was probably the part of my answer with the most merit...
– Eden Trainor
3 hours ago
add a comment |
Building on Olivier Melançons answer, I came up with this - in case the position of the value in the tuple matters:
class GroupMap:
def __init__(self, data=None):
self.data =
if data:
self.add(data)
def add(self, data):
for idx, key in enumerate(data):
self.data.setdefault(idx, )[key] = data
def __getitem__(self, key):
# lookup in first index
return self.getby(0, key)
def getby(self, idx, key):
return self.data[idx].get(key)
data = ('a', 'b', 'c')
g = GroupMap(data)
more_data = ('b', 'a', 'z')
g.add(more_data)
assert g['a'] == data
assert g.getby(0, 'a') == data
assert g.getby(0, 'b') == more_data
assert g.getby(0, 'c') is None
assert g.getby(1, 'a') == more_data
assert g.getby(1, 'b') == data
assert g.getby(2, 'c') == data
assert g.getby(2, 'z') == more_data
assert id(data) == id(g['a']) == id(g.getby(1, 'b'))
add a comment |
Building on Olivier Melançons answer, I came up with this - in case the position of the value in the tuple matters:
class GroupMap:
def __init__(self, data=None):
self.data =
if data:
self.add(data)
def add(self, data):
for idx, key in enumerate(data):
self.data.setdefault(idx, )[key] = data
def __getitem__(self, key):
# lookup in first index
return self.getby(0, key)
def getby(self, idx, key):
return self.data[idx].get(key)
data = ('a', 'b', 'c')
g = GroupMap(data)
more_data = ('b', 'a', 'z')
g.add(more_data)
assert g['a'] == data
assert g.getby(0, 'a') == data
assert g.getby(0, 'b') == more_data
assert g.getby(0, 'c') is None
assert g.getby(1, 'a') == more_data
assert g.getby(1, 'b') == data
assert g.getby(2, 'c') == data
assert g.getby(2, 'z') == more_data
assert id(data) == id(g['a']) == id(g.getby(1, 'b'))
add a comment |
Building on Olivier Melançons answer, I came up with this - in case the position of the value in the tuple matters:
class GroupMap:
def __init__(self, data=None):
self.data =
if data:
self.add(data)
def add(self, data):
for idx, key in enumerate(data):
self.data.setdefault(idx, )[key] = data
def __getitem__(self, key):
# lookup in first index
return self.getby(0, key)
def getby(self, idx, key):
return self.data[idx].get(key)
data = ('a', 'b', 'c')
g = GroupMap(data)
more_data = ('b', 'a', 'z')
g.add(more_data)
assert g['a'] == data
assert g.getby(0, 'a') == data
assert g.getby(0, 'b') == more_data
assert g.getby(0, 'c') is None
assert g.getby(1, 'a') == more_data
assert g.getby(1, 'b') == data
assert g.getby(2, 'c') == data
assert g.getby(2, 'z') == more_data
assert id(data) == id(g['a']) == id(g.getby(1, 'b'))
Building on Olivier Melançons answer, I came up with this - in case the position of the value in the tuple matters:
class GroupMap:
def __init__(self, data=None):
self.data =
if data:
self.add(data)
def add(self, data):
for idx, key in enumerate(data):
self.data.setdefault(idx, )[key] = data
def __getitem__(self, key):
# lookup in first index
return self.getby(0, key)
def getby(self, idx, key):
return self.data[idx].get(key)
data = ('a', 'b', 'c')
g = GroupMap(data)
more_data = ('b', 'a', 'z')
g.add(more_data)
assert g['a'] == data
assert g.getby(0, 'a') == data
assert g.getby(0, 'b') == more_data
assert g.getby(0, 'c') is None
assert g.getby(1, 'a') == more_data
assert g.getby(1, 'b') == data
assert g.getby(2, 'c') == data
assert g.getby(2, 'z') == more_data
assert id(data) == id(g['a']) == id(g.getby(1, 'b'))
answered 2 hours ago
CloudomationCloudomation
882111
882111
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55892600%2fpython-triplet-dictionary%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You want to be able to recover the triplet from any of the elements?
– Olivier Melançon
3 hours ago
@OlivierMelançon For my specific problem, if I have
a1
, I'd like to knowb1
andc1
. And if I only haveb1
, I'd need to knowa1
andc1
. But I'd never havec1
directly... If that makes sense.– Justin
3 hours ago
1
perfect time to learn how to make your own data types. see docs.python.org/3/library/stdtypes.html#typesmapping
– user633183
3 hours ago
1
Quick hint: you would either need a custom mapping type (e.g. a
dict
subclass with__getitem__
overridden, at the very least) or you would need some custom container type that can wrap each item of your tuples and the tuples themselves such that they have the same__hash__
. I suspect you might have an X-Y problem though but hard to be sure.– Iguananaut
3 hours ago
2
I think it's an interesting problem. The answers given below are the most obvious but if you wanted to completely avoid duplication you'd have to do some tricks with hashes. I have to say, while it's a neat idea, in 25 years of programming I have never needed a data structure quite like this which is why I suspect an X-Y problem, but who knows stranger things have happened.
– Iguananaut
3 hours ago