isidentical commented on code in PR #3969:
URL: https://github.com/apache/arrow-datafusion/pull/3969#discussion_r1008281138


##########
datafusion/physical-expr/src/utils.rs:
##########
@@ -0,0 +1,205 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use crate::PhysicalExpr;
+use crate::PhysicalSortExpr;
+
+use std::sync::Arc;
+
+/// Compare the two expr lists are equal no matter the order.
+/// For example two InListExpr can be considered to be equals no matter the 
order:
+///
+/// In('a','b','c') == In('c','b','a')
+pub fn expr_list_eq_any_order(
+    list1: &[Arc<dyn PhysicalExpr>],
+    list2: &[Arc<dyn PhysicalExpr>],
+) -> bool {
+    if list1.len() == list2.len() {
+        let mut expr_vec1 = list1.to_vec();
+        let mut expr_vec2 = list2.to_vec();
+        while let Some(expr1) = expr_vec1.pop() {
+            if let Some(idx) = expr_vec2.iter().position(|expr2| 
expr1.eq(expr2)) {
+                expr_vec2.swap_remove(idx);
+            } else {
+                break;
+            }
+        }
+        expr_vec1.is_empty() && expr_vec2.is_empty()
+    } else {
+        false
+    }
+}
+
+/// Strictly compare the two expr lists are equal in the given order.
+pub fn expr_list_eq_strict_order(
+    list1: &[Arc<dyn PhysicalExpr>],
+    list2: &[Arc<dyn PhysicalExpr>],
+) -> bool {
+    list1.len() == list2.len() && list1.iter().zip(list2.iter()).all(|(e1, 
e2)| e1.eq(e2))
+}
+
+/// Strictly compare the two sort expr lists in the given order.
+///
+/// For Physical Sort Exprs, the order matters:
+///
+/// SortExpr('a','b','c') != SortExpr('c','b','a')
+#[allow(dead_code)]
+pub fn sort_expr_list_eq_strict_order(
+    list1: &[PhysicalSortExpr],
+    list2: &[PhysicalSortExpr],
+) -> bool {
+    list1.len() == list2.len() && list1.iter().zip(list2.iter()).all(|(e1, 
e2)| e1.eq(e2))
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use crate::expressions::Column;
+    use crate::PhysicalSortExpr;
+    use arrow::compute::SortOptions;
+    use datafusion_common::Result;
+
+    use std::sync::Arc;
+
+    #[test]
+    fn expr_list_eq_any_order_test() -> Result<()> {
+        let list1: Vec<Arc<dyn PhysicalExpr>> = vec![
+            Arc::new(Column::new("a", 0)),
+            Arc::new(Column::new("a", 0)),
+            Arc::new(Column::new("b", 1)),
+        ];
+        let list2: Vec<Arc<dyn PhysicalExpr>> = vec![
+            Arc::new(Column::new("b", 1)),
+            Arc::new(Column::new("b", 1)),
+            Arc::new(Column::new("a", 0)),
+        ];
+        assert!(!expr_list_eq_any_order(list1.as_slice(), list2.as_slice()));
+        assert!(!expr_list_eq_any_order(list2.as_slice(), list1.as_slice()));
+
+        let list3: Vec<Arc<dyn PhysicalExpr>> = vec![
+            Arc::new(Column::new("a", 0)),
+            Arc::new(Column::new("b", 1)),
+            Arc::new(Column::new("c", 2)),
+            Arc::new(Column::new("a", 0)),
+            Arc::new(Column::new("b", 1)),
+        ];
+        let list4: Vec<Arc<dyn PhysicalExpr>> = vec![
+            Arc::new(Column::new("b", 1)),
+            Arc::new(Column::new("b", 1)),
+            Arc::new(Column::new("a", 0)),
+            Arc::new(Column::new("c", 2)),
+            Arc::new(Column::new("a", 0)),
+        ];
+        assert!(expr_list_eq_any_order(list3.as_slice(), list4.as_slice()));
+        assert!(expr_list_eq_any_order(list4.as_slice(), list3.as_slice()));
+        assert!(expr_list_eq_any_order(list3.as_slice(), list3.as_slice()));
+        assert!(expr_list_eq_any_order(list4.as_slice(), list4.as_slice()));
+

Review Comment:
   If I didn't miss any, it seems like `expr_list_eq_strict_order` can be also 
tested with these (it currently seems like missing tests):
   ```suggestion
   
       assert!(expr_list_eq_strict_order(list1.as_slice(), list1.as_slice());
       assert!(expr_list_eq_strict_order(list2.as_slice(), list2.as_slice());
       assert!(expr_list_eq_strict_order(list3.as_slice(), list3.as_slice());
       assert!(expr_list_eq_strict_order(list4.as_slice(), list4.as_slice());
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to