I have two arrays, arrayA and arrayB which both have the same elements in which are PFUsers. Although arrayB is in the wrong order and needs to be in the order of arrayA. Can someone show me some code which could be able to do this?
You should be able to convert your arrays to sets and use the == operator to compare them, although sets don't allow duplicate objects. If your arrays contain duplicate objects and you want the count of different objects to effect array equality that won't work
You should be able to convert your arrays to NSCountedSet objects, which DO keep track of how many times an object is duplicated.
To sort array B into the order of array A (not particularly dealing with any duplicate objects in either array) you can sort B with a block that finds the indexes of those objects (or objects with the same objectId) and then returns the comparison of the indexes.
Related
I have 2 json files, I am putting them into 2 multidimentional arrays in python, and I need to compare them and return an array of elements deleted, added and updated.
PS: I want to do this without taking in consideration that I know the depth of the arrays.
I have a array of 2 element, when i try to convert it to NSOrderedSet it give me a size of only one element
LOG("\(listTwoElement.count)")
This line give me 2
LOG("\(NSOrderedSet.init(array: listTwoElement).count)")
this line give me only 1 element
Why conversion to NSOrderedSet change size of array ?
thanks for your help
A Set is an unordered list of unique elements. If you try to put the same element in a set twice you will only get one
An Array is an order list of elements that needn't be unique. You can have the same element may times in array.
A OrderedSet is a combination of both (but a subclass of neither). The items are ordered, like an array, but each element needs to be unique.
Unique element does not (just) mean that they are stored in different locations in memory, but that they are not "equal" in some fundamental sense. Equality can be defined differently for every class. Classes that want to define it, implement the isEqual: and hash method of the NSObjectProtocol. (Hashes of equal objects must be equal, hashes of unequal object do not need to be different).
Without knowing more about the element you are dealing with it is hard to say why they are being evaluated as equal when you don't expect them to be. I would start will looking at the class's implementation of the isEqual and hash.
I'm working to convert some of my ObjC code that uses primitive c arrays to Swift arrays. However, using a playground, I've found some strange behaviors.
For instance, the following is perfectly valid in Swift
var largearray : [[Float]] = []
largearray.append([0,1,2]) //3 elements
largearray.append([3,4,5]) //3 elements
largearray.append([6,7,8,9]) //-4- elements
largearray.append([10,11,12]) //3 elements
//pull those back out
largearray[1][0] //gives 3
largearray[1][2] //gives 5
//largearray[1][3] //error
largearray[2][0] //gives 6
largearray[2][2] //gives 8
largearray[2][3] //gives 9
largearray[3][0] //gives 10
I don't understand how it's possible to have a mixed row lengths is Swift. Can someone explain what's going on here, because the documentation doesn't go into that kind of detail. I'm curious if it is even storing a contiguous Float array behind the scenes or not.
Then another question I have is about accessing rows or columns. In Swift I see that I can access an entire row using largearray[0] gives [0,1,2], just as largearray[2] gives [6,7,8,9]. Which isn't how c arrays are indexed. (If I just specified one index for a 2D c-array, it would act as a sequential index row by column. So, is there some way to access an entire column in swift? In c, and Swift, largearray[][2] is invalid. But I'm curious if there is some technique not mentioned in the docs, since it seems obvious that Swift is keeping track of extra information.
I should add that I will be making use of the Accelerate framework. So if any of the above "strange" ways of using a Swift array will cause performance issues on massive arrays, let me know.
How are Swift arrays different than c arrays
In C, an array is always a contiguous list of elements. In Swift, an array is a much more abstract data structure. You can make assumptions about how data is organized in memory with a C array, and you can even calculate the addresses of an element given the base address, element size, and an index. In Swift, not so much. Think of Swift's Array type the same way you think of NSArray in Objective-C. It's an ordered sequence of elements that provides array-like operations, but you shouldn't worry about how it stores the actual data.
I don't understand how it's possible to have a mixed row lengths is Swift.
Well, for one thing, you're really looking at an array of arrays. If an array is an object, then an array of arrays is probably implemented as an list of object pointers rather than a contiguous series of same-sized lists. You can do the same thing with NSArray, for example, because each item in an NSArray can be an object of any type.
So, is there some way to access an entire column in swift?
You'd need to iterate over the items in the array, which are themselves arrays, and examine the element at the "column" position you're interested in. I don't think there's a faster way to do it than that.
When is it appropriate to use which of the three flattening arguments '.flat'/'.flatiter'/'.flatten'? I know that '.flat' returns a 1D iterator over an array, does this mean that the array is left in the original shape and each element in the array can be accessed with a single index (for example using a single for loop even though the array may be highly dimensional). And '.flatten' returns a complete copy of the original array flattened out into a 1D array.
Which is less resource intensive?
flatiter is just the type of the iterator object returned by flat (docs). So all you need to know about it is that it's an iterator like any other.
Obviously, flatten consumes more memory and cpu, as it creates a new array, while flat only creates the iterator object, which is super fast.
If all you need is to iterate over the array, in a flat manner, use flat.
If you need an actual flat array (for purposes other than just explicitly iterating over it), use flatten.
By identical I mean two Arrays contain same elements, order of elements in Arrays are not matter here.
The solution I came up with is like this(which turns out a wrong approach as pointed out in comments):
if the size of two Arrays are equal
See True, find all elements of Array A in Array B
All Found, find all elements of Array B in Array A
All Found, then I get conclusion two Arrays are identical
However, is there better algorithm in term of time complexity?
Let's say you have an User[] array 1 and User[] array 2. You can lop through array one and add them to Dictionary<User, int> dictionary where the key is the user and the value is a count. Then you loop through the second array and for each user in array 2 decrement the count in the dictionary (if count is greater than 1) or remove the element (if count is 1). If the user isn't in the dictionary, then you can stop, the arrays don't match.
If you get to the end and had previously checked length of the arrays is same, then the arrays match. If you hadn't checked length earlier (which of course you still should have), then you can just verify the dictionary is now empty after completely looping through array 2.
I don't know exactly what the performance of this is, but it will be faster than sorting both lists and looping through them comparing element by element. Takes more memory though, but if the arrays are not super large then memory usage shouldn't be an issue.
First, check the size of the two arrays. If they aren't equal then they don't contain the same elements.
After that, sort both the arrays in O(n lg(n)). Now, just check both the arrays element-by-element in O(n). As they are sorted, if they are equal then they will be equal in every position.
Your approach doesn't work, as it would treat [0, 1, 1] as being equal to [0, 0, 1]. Every item in A is in B and vice versa. You'd need to count the number of occurrences of each item in A and B. (You then don't need to do both, of course, if you've already checked the lengths.)
If the contents are sortable, you can sort both and then compare element-by-element, of course. That only works if you can provide a total ordering to elements though.
Sort both arrays according to a strict ordering and compare them term-by-term.
Update: Summarizing some of the points that have been raised, here the efficiency you can generally expect:
strict ordering available: O(log N) for sorting plus comparing term-by-term
equality and hash function available: compare hash counts term-by-term, plus actual object comparisons in the event of hash collisions.
only equality, no hashing available: must count each element or copy one container and remove (efficiency depends on the container).
The complexity of comparison term-by-term is linear in the position of the first mismatch.
My idea is to loop through the first array and look for items in the second array. The only issue of course is that you can't use an item in the second array twice. So, make a third array of booleans. This array indicates which items in array 2 'have been used'.
Loop through the first array. Inside that loop through each element in the second array to see if you can 'find' that element in the second array, but also check the third array to verify that the position in the second array hasn't been used. If you find a match update that position in the third array and move on.
You should only need to do this once. If you finish and you found a match for all items in array 2 then no unmatched items remain in array 2. You don't need to then loop through array 2 and see if array 1 contains the item.
Of course before you start all that check that the lengths are the same.
If you don't mind extra space you can do some like HashMap to Store the (element,count) pairs of the first array then check if the second array matches up; this would be linear in N (size of biggest array)
If the array sizes are identical and all of the elements in Array A are in Array B, then there is no need to verify that all of the elements in array B are in Array A. So at the very least you can omit that step.
EDIT: Depends on the definition of the problem. This solution would work if and only if his original solution would work, which it wouldn't if the arrays can have duplicate items and you weren't counting or marking them as "used."