diff --git a/language/buildNumber.properties b/language/buildNumber.properties
index c9bdedbd0..9348490a4 100644
--- a/language/buildNumber.properties
+++ b/language/buildNumber.properties
@@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
-#Mon Mar 25 10:44:26 CDT 2024
-buildNumber\\d*=12860
+#Wed Mar 27 14:15:30 CDT 2024
+buildNumber\\d*=12888
diff --git a/language/src/main/java/edu/uiuc/ncsa/qdl/evaluate/StemEvaluator.java b/language/src/main/java/edu/uiuc/ncsa/qdl/evaluate/StemEvaluator.java
index 051838c95..8867bb0d8 100644
--- a/language/src/main/java/edu/uiuc/ncsa/qdl/evaluate/StemEvaluator.java
+++ b/language/src/main/java/edu/uiuc/ncsa/qdl/evaluate/StemEvaluator.java
@@ -1982,7 +1982,7 @@ protected void doHasKey(Polyad polyad, State state) {
}
// if neither is a scalar, do the next bit,
}
- QDLStem result = leftArg.hasKeys(rightArg);
+ QDLStem result = leftArg.hasKey(rightArg);
polyad.setEvaluated(true);
polyad.setResult(result);
polyad.setResultType(STEM_TYPE);
@@ -2592,6 +2592,7 @@ protected void doShuffle(Polyad polyad, State state) {
* The result is that each key in arg. is renamed, but the values are not changed.
* If a key is in indices. and does not correspond to one on the left, it is skipped,
* by subsetting rule.
+ * If a key is indices and the old and new value are the same, it is skipped.
*
Limitations are that it applies to the zeroth axis, modifies arg. and
* the indices. are different than remap.
*
diff --git a/language/src/main/java/edu/uiuc/ncsa/qdl/variables/QDLStem.java b/language/src/main/java/edu/uiuc/ncsa/qdl/variables/QDLStem.java
index 3a0522dd4..69afe9f70 100644
--- a/language/src/main/java/edu/uiuc/ncsa/qdl/variables/QDLStem.java
+++ b/language/src/main/java/edu/uiuc/ncsa/qdl/variables/QDLStem.java
@@ -786,8 +786,9 @@ public QDLStem commonKeys(QDLStem arg2) {
*/
public void renameKeys(QDLStem newKeys, boolean overWriteKeys) {
for (Object oldKey : newKeys.keySet()) {
+ Object newKey = newKeys.get(oldKey);
+ if(newKey.equals(oldKey)) continue;
if (containsKey(oldKey)) {
- Object newKey = newKeys.get(oldKey);
if (containsKey(newKey)) {
if (overWriteKeys) {
Object oldValue = get(oldKey);
@@ -853,21 +854,29 @@ public QDLStem includeKeys(QDLStem keyList) {
*/
public QDLStem hasKeys(QDLStem keyList) {
QDLStem result = newInstance();
- for(Object k : keySet()){
- result.putLongOrString(k, keyList.containsKey(k));
+ if(!keyList.isList()){
+ throw new IllegalArgumentException("has keys requires a list");
+ }
+ for(Object ndx : keyList.getQDLList().orderedKeys()){
+ result.put((Long)ndx, containsKey(keyList.get((Long)ndx))); // since we know it's a list
}
-/* for (int i = 0; i < keyList.size(); i++) {
- // for loop to be sure that everything is done in order.
- String index = Integer.toString(i);
- if (!keyList.containsKey(index)) {
- throw new IllegalArgumentException("the set of supplied keys is not a list");
- }
- result.put(index, containsKey(keyList.get(index).toString()));
- }*/
return result;
}
+ /**
+ * Modern successor to the deprecated {@link #hasKeys(QDLStem)}. This returns a left conformable
+ * stem as it should.
+ * @param keyList
+ * @return
+ */
+ public QDLStem hasKey(QDLStem keyList) {
+ QDLStem result = newInstance();
+ for(Object k : keySet()){
+ result.putLongOrString(k, keyList.containsKey(k));
+ }
+ return result;
+}
/* ********
IndexEntry operations
********* */
diff --git a/tests/src/test/java/edu/uiuc/ncsa/qdl/ParserTest.java b/tests/src/test/java/edu/uiuc/ncsa/qdl/ParserTest.java
index 23d8b3722..29ee8f70f 100644
--- a/tests/src/test/java/edu/uiuc/ncsa/qdl/ParserTest.java
+++ b/tests/src/test/java/edu/uiuc/ncsa/qdl/ParserTest.java
@@ -1154,11 +1154,12 @@ public void testHasKey2() throws Throwable {
* @throws Throwable
*/
public void testHasKeys() throws Throwable {
+ // Part of https://github.com/ncsa/qdl/issues/46
State state = testUtils.getNewState();
StringBuffer script = new StringBuffer();
addLine(script, "var. := random(5);");
addLine(script, "w. := n(10);");
- addLine(script, "z. := has_keys(w., var.);");
+ addLine(script, "z. := has_keys( var., w.);");
QDLInterpreter interpreter = new QDLInterpreter(null, state);
interpreter.execute(script.toString());
// so the first 5 entries are true, the next 5 are false.