473,386 Members | 1,702 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

algorithm for "common array of longs"

Hi

I have a number of arrays of longs, from which I need to find a single
array which only contains the values which appear in all the original
arrays.

For example, I could have the three arrays:

1, 3, 2, 8, 5
3, 6, 1
6, 1, 4, 3

from which I need to generate the "common" array:
1, 3
(as these are the only values which appear in all the original arrays).
What is a good algorithm for this? The below is what I have written,
which does seem to do what I want. But more than likely there is a much
better, more efficient way to do this...

static void Main(string[] args)
{
long[] x = new long[5] { 1, 3, 2, 8, 5 };
long[] y = new long[3] { 3, 6, 1 };
long[] z = new long[4] { 6, 1, 4, 3 };

List<long[]originals = new List<long[]{ x, y, x };

long[] commonArray = Common(originals);
}

static long[] Common(List<long[]originals)
{
long[] temp = originals[0];

for (int i = 1; i < originals.Count; i++)
{
temp = Common(temp, originals[i]);
}

return temp;
}

static long[] Common(long[] one, long[] two)
{
List<longcommon = new List<long>();
foreach (long val in one)
{
if (two.Contains(val))
{
common.Add(val);
}
}
return common.ToArray();
}
Thanks,
Peter
Oct 1 '08 #1
6 1718
If the lists are large and sorted, a double walk over the 'index' in
parallel can be implemented. If the list are short and not sorted, the list
can be walked through, kind of what you did, rather than first sorted and
next using a index walk in parallel, because the time spent to sort them may
be more than what you will win by using the double walk on the 'index'. That
is why SQL has execution plan based on statistics: given different cases,
the 'imperative code' used will be different. There is also a question of
memory: can you use a lot or are you limited to the strict minimum? Anyhow,
here how a walk on index in parallel works (note that it is what SQL can
perform to execute an INNER JOIN between two lists with no dup).

0. R is an empty list,
FingerA points to before the start of the listA
FingerB points to before the start of the listB
1. Finger A points the next item in list A, itemA
2. If fingerA points to nothing, it is done.
3. Find next item in listB equals to itemA
3a. If none is found, goto 1
4. Append itemA to R
5. Move FingerB to the next item in listB, itemB
6. If fingerB points to nothing, it is done.
7. Find next item in listA equals to itemB
7a. If none if found, goto 5
8. Append itemB to R
9 Goto 1.
note that you can change lightly the algorithm if listB has duplicated
values (I assumed both list have not dup), but I don't think this is the
kind of JOIN you want.

Example: listA: 1, 2, 3, 5, 8
list B: 1, 5, 6

Step 1: fa -1
Step 3: fb-1, R =={ 1 }
Step 5: fb-5
Step 7: fa-5, R =={ 1, 5 }
Step 1: fa->8
Step 3a.
Step 1: fa-eof
so, R={ 1, 5 }

Now, for the code... I would use SQL, but feel free to do it in C# though
:-)

Vanderghast, Access MVP

"Peter" <xd****@hotmail.comwrote in message
news:OX**************@TK2MSFTNGP06.phx.gbl...
Hi

I have a number of arrays of longs, from which I need to find a single
array which only contains the values which appear in all the original
arrays.

For example, I could have the three arrays:

1, 3, 2, 8, 5
3, 6, 1
6, 1, 4, 3

from which I need to generate the "common" array:
1, 3
(as these are the only values which appear in all the original arrays).
What is a good algorithm for this? The below is what I have written,
which does seem to do what I want. But more than likely there is a much
better, more efficient way to do this...

static void Main(string[] args)
{
long[] x = new long[5] { 1, 3, 2, 8, 5 };
long[] y = new long[3] { 3, 6, 1 };
long[] z = new long[4] { 6, 1, 4, 3 };

List<long[]originals = new List<long[]{ x, y, x };

long[] commonArray = Common(originals);
}

static long[] Common(List<long[]originals)
{
long[] temp = originals[0];

for (int i = 1; i < originals.Count; i++)
{
temp = Common(temp, originals[i]);
}

return temp;
}

static long[] Common(long[] one, long[] two)
{
List<longcommon = new List<long>();
foreach (long val in one)
{
if (two.Contains(val))
{
common.Add(val);
}
}
return common.ToArray();
}
Thanks,
Peter
Oct 1 '08 #2
Peter wrote:
Hi

I have a number of arrays of longs, from which I need to find a single
array which only contains the values which appear in all the original
arrays.

For example, I could have the three arrays:

1, 3, 2, 8, 5
3, 6, 1
6, 1, 4, 3

from which I need to generate the "common" array:
You need the intersection of different sets. Intersect the first with
the second and the result with the third. There are plenty of
algorithms to do that. I have a few (relying on the sets of numbers
being sorted), but they are unfortunately not in C#.

A quick translation (may be faulty) - note that the lists must be
sorted for this to work - it is generally much faster than calling
Contains() in a loop:

public static int SetIntersection<T>(IList<Tsource1,
IList<Tsource2, IList<Tdestination, IComparer<Tcomparer)
{
int i1 = 0;
int i2 = 0;
int d = 0;
while (i1 < source1.Count && i2 < source2.Count)
{
int comp = comparer.Compare(source1[i1], source2[i2]);
if (comp < 0)
i1++;
else if (comp 0)
i2++;
else
{
destination[d] = source1[i1];
i1++;
i2++;
d++;
}
}
return d;
}

Of course destination must be big enough to contain the largest of the
source lists entirely.

if list1, list2 and list3 are the 3 lists, then do

int len = SetIntersection<int>(list1, list2, intermediate,
Comparer<int>.Default);
intermediate.DeleteRange(len, intermediate.Count - len);
len = SetIntersection<int>(intermediate, list3, result,
Comparer<int>.Default);
result.DeleteRange(len, result.Count - len);

And result will contain the elements present in all. You could modify
the routine to pass d back as well, so you know the number of items
written to it.
--
Rudy Velthuis http://rvelthuis.de

"We are not retreating - we are advancing in another Direction."
-- General Douglas MacArthur (1880-1964)
Oct 1 '08 #3
Peter wrote:
Hi

I have a number of arrays of longs, from which I need to find a single
array which only contains the values which appear in all the original
arrays.

For example, I could have the three arrays:

1, 3, 2, 8, 5
3, 6, 1
6, 1, 4, 3

from which I need to generate the "common" array:
1, 3
(as these are the only values which appear in all the original arrays).
What is a good algorithm for this? The below is what I have written,
which does seem to do what I want. But more than likely there is a much
better, more efficient way to do this...

static void Main(string[] args)
{
long[] x = new long[5] { 1, 3, 2, 8, 5 };
long[] y = new long[3] { 3, 6, 1 };
long[] z = new long[4] { 6, 1, 4, 3 };

List<long[]originals = new List<long[]{ x, y, x };

long[] commonArray = Common(originals);
}

static long[] Common(List<long[]originals)
{
long[] temp = originals[0];

for (int i = 1; i < originals.Count; i++)
{
temp = Common(temp, originals[i]);
}

return temp;
}

static long[] Common(long[] one, long[] two)
{
List<longcommon = new List<long>();
foreach (long val in one)
{
if (two.Contains(val))
{
common.Add(val);
}
}
return common.ToArray();
}
Thanks,
Peter
The Contains method for a List gets slower the larger the list is, a
HashSet scales much better:

static long[] Common(long[] one, long[] two) {
HashSet<longset = new HashSet<long>(two);
List<longcommon = new List<long>();
foreach (long val in one) {
if (set.Contains(val)) common.Add(val);
}
return common.ToArray();
}

--
Göran Andersson
_____
http://www.guffa.com
Oct 1 '08 #4
Seems much more compact that the pseudo code I tried to used...and working
fine. I would use destination.Add( source1[i1] ) instead of
destination[d]=source1[i1], though.

I wonder what LINQ.Intesect uses?

Int[] first = { 1, 3, 2, 8, 5};
Int[] second = { 6, 1, 4, 3};
IEnumerable<intcommon = first.Intersect(second);
Vanderghast, Access MVP

"Rudy Velthuis" <ne********@rvelthuis.dewrote in message
news:xn**************@news.microsoft.com...
Peter wrote:
>Hi

I have a number of arrays of longs, from which I need to find a single
array which only contains the values which appear in all the original
arrays.

For example, I could have the three arrays:

1, 3, 2, 8, 5
3, 6, 1
6, 1, 4, 3

from which I need to generate the "common" array:

You need the intersection of different sets. Intersect the first with
the second and the result with the third. There are plenty of
algorithms to do that. I have a few (relying on the sets of numbers
being sorted), but they are unfortunately not in C#.

A quick translation (may be faulty) - note that the lists must be
sorted for this to work - it is generally much faster than calling
Contains() in a loop:

public static int SetIntersection<T>(IList<Tsource1,
IList<Tsource2, IList<Tdestination, IComparer<Tcomparer)
{
int i1 = 0;
int i2 = 0;
int d = 0;
while (i1 < source1.Count && i2 < source2.Count)
{
int comp = comparer.Compare(source1[i1], source2[i2]);
if (comp < 0)
i1++;
else if (comp 0)
i2++;
else
{
destination[d] = source1[i1];
i1++;
i2++;
d++;
}
}
return d;
}

Of course destination must be big enough to contain the largest of the
source lists entirely.

if list1, list2 and list3 are the 3 lists, then do

int len = SetIntersection<int>(list1, list2, intermediate,
Comparer<int>.Default);
intermediate.DeleteRange(len, intermediate.Count - len);
len = SetIntersection<int>(intermediate, list3, result,
Comparer<int>.Default);
result.DeleteRange(len, result.Count - len);

And result will contain the elements present in all. You could modify
the routine to pass d back as well, so you know the number of items
written to it.
--
Rudy Velthuis http://rvelthuis.de

"We are not retreating - we are advancing in another Direction."
-- General Douglas MacArthur (1880-1964)
Oct 1 '08 #5
Michel Walsh wrote:
Seems much more compact that the pseudo code I tried to used...and
working fine. I would use destination.Add( source1[i1] ) instead of
destination[d]=source1[i1], though.
I designed mine to work with arrays too.
I wonder what LINQ.Intesect uses?

Int[] first = { 1, 3, 2, 8, 5};
Int[] second = { 6, 1, 4, 3};
IEnumerable<intcommon = first.Intersect(second);
I translated that from a language without LINQ. <g>

I guess LINQ would be a lot easier.
--
Rudy Velthuis http://rvelthuis.de

"Our children are not born to hate, they are raised to hate."
-- Thomas della Peruta
Oct 1 '08 #6
Göran Andersson brought next idea :
Peter wrote:
>Hi

I have a number of arrays of longs, from which I need to find a single
array which only contains the values which appear in all the original
arrays.

For example, I could have the three arrays:

1, 3, 2, 8, 5
3, 6, 1
6, 1, 4, 3

from which I need to generate the "common" array:
1, 3
(as these are the only values which appear in all the original arrays).
What is a good algorithm for this? The below is what I have written,
which does seem to do what I want. But more than likely there is a much
better, more efficient way to do this...

static void Main(string[] args)
{
long[] x = new long[5] { 1, 3, 2, 8, 5 };
long[] y = new long[3] { 3, 6, 1 };
long[] z = new long[4] { 6, 1, 4, 3 };

List<long[]originals = new List<long[]{ x, y, x };

long[] commonArray = Common(originals);
}

static long[] Common(List<long[]originals)
{
long[] temp = originals[0];

for (int i = 1; i < originals.Count; i++)
{
temp = Common(temp, originals[i]);
}

return temp;
}

static long[] Common(long[] one, long[] two)
{
List<longcommon = new List<long>();
foreach (long val in one)
{
if (two.Contains(val))
{
common.Add(val);
}
}
return common.ToArray();
}
Thanks,
Peter

The Contains method for a List gets slower the larger the list is, a HashSet
scales much better:

static long[] Common(long[] one, long[] two) {
HashSet<longset = new HashSet<long>(two);
List<longcommon = new List<long>();
foreach (long val in one) {
if (set.Contains(val)) common.Add(val);
}
return common.ToArray();
}
If you are using HashSets, why not:

long[] x = new long[5] { 1, 3, 2, 8, 5 };
long[] y = new long[3] { 3, 6, 1 };
long[] z = new long[4] { 6, 1, 4, 3 };

HashSet<longhs1 = new HashSet<long>(x);
hs1.IntersectWith(y);
hs1.IntersectWith(z);

foreach(var l in hs1)
Console.WriteLine(l);
(returns 1 and 3)

Hans Kesting
Oct 2 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Arnaud | last post by:
Hi, I work with php 4.3.4 and I don't understand the way php sort this array for example : <? $array = (-1, 30, "test", true); sort($array); var_dump($array); ?>
7
by: Sherry Littletree | last post by:
Hi All I am working on a site that has a large amount of common html on all its web pages. I am looking for a way to place this in a single file so, if changes are made, I can change this...
6
by: sonic | last post by:
what exactly is the difference ? I think that is more suitable for declarative arrays, but not exactly sure why. TIA
4
by: Greg Stark | last post by:
I find myself wishing I had a syntax "LIKE ANY (array)". I don't see much value in the = ANY, = ALL, <> ANY, <> ALL syntax since they're equivalent more or less to IN and NOT IN. But it could be...
0
by: Klemens | last post by:
what do entry's like this in db2diag.log indicate? ------------------------------------------- 2004-01-14-09.07.52.650000 Instance:WWS Node:000 PID:3512(db2syscs.exe) TID:1116 ...
2
by: Simon Morgan | last post by:
I hope this isn't OT, I looked for a newsgroup dealing purely with algorithms but none were to be found and seeing as I'm trying to implement this in C I thought this would be the best place. I...
3
by: Pablo Gutierrez | last post by:
I have a C# method that reads Binary data (BLOB type) from a database and returns the data an array of bytes (i.e byte outbyte = new byte;). The BLOB column is saved into the database by a C...
5
by: Jim Carlock | last post by:
I've set up the following using an Alias in Apache... Alias /phpdocs/ "C:/Apache/htdocs/common/docs/php/" <Directory "C:/Apache/htdocs/common/docs/php"> Options Indexes FollowSymlinks MultiViews...
30
by: josh | last post by:
Hi all, what does it meaning that strange sintax (look at the object :) ? if I have i.e. array.length I can use array. and is it IE/Firefox compatible??
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.