Skip to content

Commit

Permalink
Fix order of edge or vertex attributes
Browse files Browse the repository at this point in the history
When edge or vertex attributes are added via `add.attributes.to.network`, as of
igraph version 1.4.0, existing attributes are not re-added or re-ordered. That
is, if attributes `name` and `type` already exist and ones adds the new
attributes `kind` and `type`, then `kind` is added after `type` as `type`
already existed. However, this breaks the ordering of the attributes and leads
to failing tests, as the order of the attributes is also tested in some of our
tests. To fix this problem, remove and re-add an attribute that was already
present before. This way, we make sure that the new attributes are added in the
expected order. (The only exception is the `name` attribute: This attribute is
expected to be the first attribute, and it should not be removed and readded as
this could lead to serious problems.)

This addresses se-sic#236.

Signed-off-by: Thomas Bock <bockthom@cs.uni-saarland.de>
  • Loading branch information
bockthom committed Apr 2, 2023
1 parent 98a6deb commit b8232c0
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions util-networks.R
Original file line number Diff line number Diff line change
Expand Up @@ -1367,11 +1367,15 @@ add.attributes.to.network = function(network, type = c("vertex", "edge"), attrib
## get type
type = match.arg(type, several.ok = FALSE)

## get corresponding attribute function
## get corresponding attribute functions
if (type == "vertex") {
attribute.function = igraph::set.vertex.attribute # sprintf("igraph::set.%s.attribute", type)
attribute.set.function = igraph::set.vertex.attribute # sprintf("igraph::set.%s.attribute", type)
attribute.get.function = igraph::get.vertex.attribute # sprintf("igraph::get.%s.attribute", type)
attribute.remove.function = igraph::remove.vertex.attribute # sprintf("igraph::remove.%s.attribute", type)
} else {
attribute.function = igraph::set.edge.attribute # sprintf("igraph::set.%s.attribute", type)
attribute.set.function = igraph::set.edge.attribute # sprintf("igraph::set.%s.attribute", type)
attribute.get.function = igraph::get.edge.attribute # sprintf("igraph::get.%s.attribute", type)
attribute.remove.function = igraph::remove.edge.attribute # sprintf("igraph::remove.%s.attribute", type)
}

## iterate over all wanted attribute names and add the attribute with the wanted class
Expand All @@ -1385,6 +1389,16 @@ add.attributes.to.network = function(network, type = c("vertex", "edge"), attrib
if (lubridate::is.POSIXct(default.value)) {
attr(default.value, "tzone") = TIMEZONE
}

## check if the attribute is already present. If so, remove it and re-add it (to keep the intended order).
## only exception from this: the name attribute is not removed and re-added, as this would lead to problems.
if (!is.null(attribute.get.function(network, attr.name)) && attr.name != "name") {
logging::logwarn("Attribute %s has already been present, but is re-added now.", attr.name)
present.value = attribute.get.function(network, attr.name)
network = attribute.remove.function(network, attr.name)
default.value = present.value
}

## add the new attribute to the network with the proper class
network = attribute.set.function(network, attr.name, value = default.value)
}
Expand Down

0 comments on commit b8232c0

Please sign in to comment.