mirror of
https://github.com/gnosygnu/xowa.git
synced 2024-10-27 20:34:16 +00:00
XOMW: Add PHP array-diff and array-diff-key [#632]
This commit is contained in:
parent
ebe82bea6a
commit
04c499ce3e
@ -30,10 +30,14 @@ import gplx.core.brys.Bry_bfr_able;
|
|||||||
import gplx.core.strings.String_bldr;
|
import gplx.core.strings.String_bldr;
|
||||||
import gplx.core.strings.String_bldr_;
|
import gplx.core.strings.String_bldr_;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
// REF.PHP: https://www.php.net/manual/en/language.types.array.php
|
// REF.PHP:https://www.php.net/manual/en/language.types.array.php
|
||||||
// also has static functions; REF.PHP: https://www.php.net/manual/en/ref.array.php
|
// also has static functions; REF.PHP:https://www.php.net/manual/en/ref.array.php
|
||||||
public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
||||||
private final Ordered_hash hash = Ordered_hash_.New();
|
private final Ordered_hash hash = Ordered_hash_.New();
|
||||||
private int newMemberIdx;
|
private int newMemberIdx;
|
||||||
@ -138,6 +142,9 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key);
|
XophpArrayItm itm = (XophpArrayItm)hash.Get_by(key);
|
||||||
return itm == null ? null : (T)itm.Val();
|
return itm == null ? null : (T)itm.Val();
|
||||||
}
|
}
|
||||||
|
public XophpArrayItm Get_by_itm(String key) {
|
||||||
|
return (XophpArrayItm)hash.Get_by(key);
|
||||||
|
}
|
||||||
public void Set(int key, Object val) {
|
public void Set(int key, Object val) {
|
||||||
this.Set(XophpArrayItm.NewInt(key, val));
|
this.Set(XophpArrayItm.NewInt(key, val));
|
||||||
}
|
}
|
||||||
@ -160,6 +167,9 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
hash.Del(itm.Key());
|
hash.Del(itm.Key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void Del_by(String key) {
|
||||||
|
hash.Del(key);
|
||||||
|
}
|
||||||
public XophpArrayItm[] To_ary() {
|
public XophpArrayItm[] To_ary() {
|
||||||
return (XophpArrayItm[])hash.To_ary(XophpArrayItm.class);
|
return (XophpArrayItm[])hash.To_ary(XophpArrayItm.class);
|
||||||
}
|
}
|
||||||
@ -309,7 +319,7 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
return len == 0 ? null : ((XophpArrayItm)array.hash.Get_at(len - 1)).Val();
|
return len == 0 ? null : ((XophpArrayItm)array.hash.Get_at(len - 1)).Val();
|
||||||
}
|
}
|
||||||
|
|
||||||
// REF.PHP: https://www.php.net/manual/en/function.array-values.php
|
// REF.PHP:https://www.php.net/manual/en/function.array-values.php
|
||||||
public static XophpArray array_values(XophpArray array) {
|
public static XophpArray array_values(XophpArray array) {
|
||||||
XophpArray rv = new XophpArray();
|
XophpArray rv = new XophpArray();
|
||||||
int len = array.Len();
|
int len = array.Len();
|
||||||
@ -482,7 +492,7 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
return sb.To_str_and_clear();
|
return sb.To_str_and_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// REF.PHP: https://www.php.net/manual/en/function.in-array.php
|
// REF.PHP:https://www.php.net/manual/en/function.in-array.php
|
||||||
public static boolean in_array(Object needle, XophpArray haystack) {return in_array(needle, haystack, false);}
|
public static boolean in_array(Object needle, XophpArray haystack) {return in_array(needle, haystack, false);}
|
||||||
public static boolean in_array(Object needle, XophpArray haystack, boolean strict) {
|
public static boolean in_array(Object needle, XophpArray haystack, boolean strict) {
|
||||||
// if strict, cache needleType
|
// if strict, cache needleType
|
||||||
@ -519,7 +529,7 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// REF.PHP: https://www.php.net/manual/en/function.array-shift.php
|
// REF.PHP:https://www.php.net/manual/en/function.array-shift.php
|
||||||
// Returns the shifted value, or NULL if array is empty or is not an array.
|
// Returns the shifted value, or NULL if array is empty or is not an array.
|
||||||
public static Object array_shift(XophpArray array) {
|
public static Object array_shift(XophpArray array) {
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
@ -544,7 +554,7 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
return itms[0].Val();
|
return itms[0].Val();
|
||||||
}
|
}
|
||||||
|
|
||||||
// REF.PHP: https://www.php.net/manual/en/function.array-filter.php
|
// REF.PHP:https://www.php.net/manual/en/function.array-filter.php
|
||||||
public static final int ARRAY_FILTER_USE_BOTH = 1, ARRAY_FILTER_USE_KEY = 2, ARRAY_FILTER_USE_VAL = 0; // XO:USE_VAL is not PHP
|
public static final int ARRAY_FILTER_USE_BOTH = 1, ARRAY_FILTER_USE_KEY = 2, ARRAY_FILTER_USE_VAL = 0; // XO:USE_VAL is not PHP
|
||||||
public static XophpArray array_filter(XophpArray array) {return array_filter(array, NULL_CALLBACK, 0);}
|
public static XophpArray array_filter(XophpArray array) {return array_filter(array, NULL_CALLBACK, 0);}
|
||||||
public static XophpArray array_filter(XophpArray array, XophpCallback callback) {return array_filter(array, callback, 0);}
|
public static XophpArray array_filter(XophpArray array, XophpCallback callback) {return array_filter(array, callback, 0);}
|
||||||
@ -578,4 +588,70 @@ public class XophpArray<T> implements Bry_bfr_able, Iterable<T> {
|
|||||||
return !XophpObject_.empty_obj(arg);
|
return !XophpObject_.empty_obj(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// REF.PHP:https://www.php.net/manual/en/function.array-diff.php
|
||||||
|
public static XophpArray array_diff(XophpArray array1, XophpArray array2, XophpArray... arrays) {
|
||||||
|
// remove elements
|
||||||
|
Map<String, List<String>> valMap = array_diff__build_val_map(array1);
|
||||||
|
int array1_len = array1.Len();
|
||||||
|
array_diff__remove_common_vals(valMap, array1, array2);
|
||||||
|
for (XophpArray array : arrays) {
|
||||||
|
// update map, if array contents changed
|
||||||
|
if (array1_len != array1.Len()) {
|
||||||
|
valMap = array_diff__build_val_map(array1);
|
||||||
|
array1_len = array1.Len();
|
||||||
|
}
|
||||||
|
array_diff__remove_common_vals(valMap, array1, array);
|
||||||
|
}
|
||||||
|
return array1;
|
||||||
|
}
|
||||||
|
private static Map<String, List<String>> array_diff__build_val_map(XophpArray array) {
|
||||||
|
Map<String, List<String>> map = new HashMap<>();
|
||||||
|
int len = array.Len();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
XophpArrayItm itm = array.Get_at_itm(i);
|
||||||
|
|
||||||
|
// get val as String
|
||||||
|
String valStr = XophpObject_.ToStr(itm.Val());
|
||||||
|
List<String> keyList = map.get(valStr);
|
||||||
|
if (keyList == null) {
|
||||||
|
keyList = new ArrayList<>();
|
||||||
|
map.put(valStr, keyList);
|
||||||
|
}
|
||||||
|
keyList.add(itm.Key());
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
private static void array_diff__remove_common_vals(Map<String, List<String>> lhsValMap, XophpArray lhs, XophpArray rhs) {
|
||||||
|
int rhsLen = rhs.Len();
|
||||||
|
for (int i = 0; i < rhsLen; i++) {
|
||||||
|
XophpArrayItm rhsItm = rhs.Get_at_itm(i);
|
||||||
|
String rhsVal = XophpObject_.ToStr(rhsItm.Val());
|
||||||
|
List<String> lhsKeyList = lhsValMap.get(rhsVal);
|
||||||
|
if (lhsKeyList != null) {
|
||||||
|
for (String lhsKey : lhsKeyList) {
|
||||||
|
lhs.Del_by(lhsKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// REF.PHP:https://www.php.net/manual/en/function.array-diff-key
|
||||||
|
public static XophpArray array_diff_key(XophpArray array1, XophpArray array2, XophpArray... arrays) {
|
||||||
|
// remove elements
|
||||||
|
array_diff_key__remove_common_key(array1, array2);
|
||||||
|
for (XophpArray array : arrays) {
|
||||||
|
array_diff_key__remove_common_key(array1, array);
|
||||||
|
}
|
||||||
|
return array1;
|
||||||
|
}
|
||||||
|
private static void array_diff_key__remove_common_key(XophpArray lhs, XophpArray rhs) {
|
||||||
|
int rhsLen = rhs.Len();
|
||||||
|
for (int i = 0; i < rhsLen; i++) {
|
||||||
|
XophpArrayItm rhsItm = rhs.Get_at_itm(i);
|
||||||
|
String rhsKey = rhsItm.Key();
|
||||||
|
if (lhs.Has(rhsKey)) {
|
||||||
|
lhs.Del_by(rhsKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ import gplx.String_;
|
|||||||
import gplx.Type_;
|
import gplx.Type_;
|
||||||
import gplx.core.brys.Bry_bfr_able;
|
import gplx.core.brys.Bry_bfr_able;
|
||||||
|
|
||||||
public class XophpArrayItm implements Bry_bfr_able {
|
public class XophpArrayItm<T> implements Bry_bfr_able {
|
||||||
XophpArrayItm(boolean keyIsInt, int keyAsInt, String key, Object val) {
|
XophpArrayItm(boolean keyIsInt, int keyAsInt, String key, T val) {
|
||||||
this.keyIsInt = keyIsInt;
|
this.keyIsInt = keyIsInt;
|
||||||
this.keyAsInt = keyAsInt;
|
this.keyAsInt = keyAsInt;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
@ -33,7 +33,7 @@ public class XophpArrayItm implements Bry_bfr_able {
|
|||||||
public boolean KeyIsInt() {return keyIsInt;} private final boolean keyIsInt;
|
public boolean KeyIsInt() {return keyIsInt;} private final boolean keyIsInt;
|
||||||
public int KeyAsInt() {return keyAsInt;} private final int keyAsInt;
|
public int KeyAsInt() {return keyAsInt;} private final int keyAsInt;
|
||||||
public String Key() {return key;} private final String key;
|
public String Key() {return key;} private final String key;
|
||||||
public Object Val() {return val;} public void Val_(Object v) {this.val = v;} private Object val;
|
public T Val() {return val;} public void Val_(T v) {this.val = v;} private T val;
|
||||||
|
|
||||||
public void To_bfr(Bry_bfr bfr) {
|
public void To_bfr(Bry_bfr bfr) {
|
||||||
bfr.Add_str_u8(key).Add_byte_eq();
|
bfr.Add_str_u8(key).Add_byte_eq();
|
||||||
|
@ -96,4 +96,9 @@ public class XophpObject_ {
|
|||||||
|
|
||||||
// equivalent to ??
|
// equivalent to ??
|
||||||
public static Object Coalesce(Object o, Object or) {return isset_obj(o) ? o : or;}
|
public static Object Coalesce(Object o, Object or) {return isset_obj(o) ? o : or;}
|
||||||
|
|
||||||
|
// equivalent to (string)o; see https://www.php.net/manual/en/function.array-diff.php
|
||||||
|
public static String ToStr(Object o) {
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,15 +15,12 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
|
|||||||
*/
|
*/
|
||||||
package gplx.xowa.mediawiki.includes.libs.services;
|
package gplx.xowa.mediawiki.includes.libs.services;
|
||||||
|
|
||||||
import gplx.xowa.mediawiki.XophpArray;
|
|
||||||
import gplx.xowa.mediawiki.XophpArray;
|
import gplx.xowa.mediawiki.XophpArray;
|
||||||
import gplx.xowa.mediawiki.XophpCallback;
|
import gplx.xowa.mediawiki.XophpCallback;
|
||||||
import gplx.xowa.mediawiki.XophpObject_;
|
import gplx.xowa.mediawiki.XophpObject_;
|
||||||
import gplx.xowa.mediawiki.XophpType_;
|
import gplx.xowa.mediawiki.XophpType_;
|
||||||
/*
|
/*
|
||||||
XOTODO:
|
XOTODO:
|
||||||
* array_diff: https://www.php.net/manual/en/function.array-diff.php
|
|
||||||
* array_diff_key: https://www.php.net/manual/en/function.array-diff-key
|
|
||||||
* XomwAssert: /vendor/wikimedia/Assert/src
|
* XomwAssert: /vendor/wikimedia/Assert/src
|
||||||
*/
|
*/
|
||||||
// MW.SRC:1.33.1
|
// MW.SRC:1.33.1
|
||||||
|
@ -389,6 +389,60 @@ public class XophpArrayStaticTest {
|
|||||||
XophpArray.reset(array);
|
XophpArray.reset(array);
|
||||||
Gftest.Eq__str("step one", (String)XophpArray.current(array));
|
Gftest.Eq__str("step one", (String)XophpArray.current(array));
|
||||||
}
|
}
|
||||||
|
@Test public void array_diff() {
|
||||||
|
// test To_str
|
||||||
|
XophpArray<String> array1 = new XophpArray().Add("a", "0");
|
||||||
|
XophpArray<Integer> arrayInt = new XophpArray().Add("a", 0);
|
||||||
|
|
||||||
|
fxt.Test__eq
|
||||||
|
( new XophpArray<String>()
|
||||||
|
, XophpArray.array_diff(array1, arrayInt)
|
||||||
|
);
|
||||||
|
|
||||||
|
// test many
|
||||||
|
XophpArray<String> array2, array3, array4;
|
||||||
|
array1 = new XophpArray().Add_many("a", "b", "c", "d");
|
||||||
|
array2 = new XophpArray().Add_many("a");
|
||||||
|
array3 = new XophpArray().Add_many("c");
|
||||||
|
array4 = new XophpArray().Add_many("d");
|
||||||
|
|
||||||
|
fxt.Test__eq
|
||||||
|
( new XophpArray<String>().Add(1, "b")
|
||||||
|
, XophpArray.array_diff(array1, array2, array3, array4)
|
||||||
|
);
|
||||||
|
|
||||||
|
// PHP examples
|
||||||
|
// Example #1 array_diff() example
|
||||||
|
array1 = new XophpArray().Add("a", "green").Add_many("red", "blue", "red");
|
||||||
|
array2 = new XophpArray().Add("b", "green").Add_many("yellow", "red");
|
||||||
|
|
||||||
|
fxt.Test__eq
|
||||||
|
( new XophpArray<String>().Add(1, "blue")
|
||||||
|
, XophpArray.array_diff(array1, array2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@Test public void array_diff_key() {
|
||||||
|
// PHP examples
|
||||||
|
// Example #1 array_diff_key() example
|
||||||
|
XophpArray<Integer> array1, array2;
|
||||||
|
array1 = new XophpArray<>().Add("blue", 1).Add("red", 2).Add("green", 3).Add("purple", 4);
|
||||||
|
array2 = new XophpArray<>().Add("green", 5).Add("yellow", 7).Add("cyan", 8);
|
||||||
|
|
||||||
|
fxt.Test__eq
|
||||||
|
( new XophpArray<String>().Add("blue", 1).Add("red", 2).Add("purple", 4)
|
||||||
|
, XophpArray.array_diff_key(array1, array2)
|
||||||
|
);
|
||||||
|
|
||||||
|
XophpArray<Integer> array3;
|
||||||
|
array1 = new XophpArray<>().Add("blue", 1).Add("red", 2).Add("green", 3).Add("purple", 4);
|
||||||
|
array2 = new XophpArray<>().Add("green", 5).Add("yellow", 7).Add("cyan", 8);
|
||||||
|
array3 = new XophpArray<>().Add("blue", 6).Add("yellow", 7).Add("mauve", 8);
|
||||||
|
|
||||||
|
fxt.Test__eq
|
||||||
|
( new XophpArray<String>().Add("red", 2).Add("purple", 4)
|
||||||
|
, XophpArray.array_diff_key(array1, array2, array3)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class XophpArray_fxt {
|
class XophpArray_fxt {
|
||||||
public XophpArray Make() {return new XophpArray();}
|
public XophpArray Make() {return new XophpArray();}
|
||||||
|
Loading…
Reference in New Issue
Block a user