Giter Site home page Giter Site logo

hankcs / ahocorasickdoublearraytrie Goto Github PK

View Code? Open in Web Editor NEW
929.0 63.0 285.0 3.13 MB

An extremely fast implementation of Aho Corasick algorithm based on Double Array Trie.

Home Page: http://www.hankcs.com/program/algorithm/aho-corasick-double-array-trie.html

Java 100.00%
aho-corasick doublearraytrie algorithm java fast

ahocorasickdoublearraytrie's Introduction

AhoCorasickDoubleArrayTrie

Maven Central GitHub release License

An extremely fast implementation of Aho Corasick algorithm based on Double Array Trie structure. Its speed is 5 to 9 times of naive implementations, perhaps it's the fastest implementation so far ;-)

Introduction

You may heard that Aho-Corasick algorithm is fast for parsing text with a huge dictionary, for example:

  • looking for certain words in texts in order to URL link or emphasize them
  • adding semantics to plain text
  • checking against a dictionary to see if syntactic errors were made

But most implementation use a TreeMap<Character, State> to store the goto structure, which costs O(lg(t)) time, t is the largest amount of a word's common prefixes. The final complexity is O(n * lg(t)), absolutely t > 2, so n * lg(t) > n . The others used a HashMap, which wasted too much memory, and still remained slowly.

I improved it by replacing the XXXMap to a Double Array Trie, whose time complexity is just O(1), thus we get a total complexity of exactly O(n), and take a perfect balance of time and memory. Yes, its speed is not related to the length or language or common prefix of the words of a dictionary.

This implementation has been widely used in my HanLP: Han Language Processing package. I hope it can serve as a common data structure library in projects handling text or NLP task.

Dependency

Include this dependency in your POM. Be sure to check for the latest version in Maven Central.

<dependency>
  <groupId>com.hankcs</groupId>
  <artifactId>aho-corasick-double-array-trie</artifactId>
  <version>1.2.3</version>
</dependency>

or include this dependency in your build.gradle.kts

implementation("com.hankcs:aho-corasick-double-array-trie:1.2.2")

Usage

Setting up the AhoCorasickDoubleArrayTrie is a piece of cake:

        // Collect test data set
        TreeMap<String, String> map = new TreeMap<String, String>();
        String[] keyArray = new String[]
                {
                        "hers",
                        "his",
                        "she",
                        "he"
                };
        for (String key : keyArray)
        {
            map.put(key, key);
        }
        // Build an AhoCorasickDoubleArrayTrie
        AhoCorasickDoubleArrayTrie<String> acdat = new AhoCorasickDoubleArrayTrie<String>();
        acdat.build(map);
        // Test it
        final String text = "uhers";
        List<AhoCorasickDoubleArrayTrie.Hit<String>> wordList = acdat.parseText(text);

Of course, there remains many useful methods to be discovered, feel free to try:

  • Use a Map<String, SomeObject> to assign a SomeObject as value to a keyword.
  • Store the AhoCorasickDoubleArrayTrie to disk by calling save method.
  • Restore the AhoCorasickDoubleArrayTrie from disk by calling load method.
  • Use it in concurrent code. AhoCorasickDoubleArrayTrie is thread safe after build method

In other situations you probably do not need a huge wordList, then please try this:

        acdat.parseText(text, new AhoCorasickDoubleArrayTrie.IHit<String>()
        {
            @Override
            public void hit(int begin, int end, String value)
            {
                System.out.printf("[%d:%d]=%s\n", begin, end, value);
            }
        });

or a lambda function

        acdat.parseText(text, (begin, end, value) -> {
            System.out.printf("[%d:%d]=%s\n", begin, end, value);
        });

Comparison

I compared my AhoCorasickDoubleArrayTrie with robert-bor's aho-corasick, ACDAT represents for AhoCorasickDoubleArrayTrie and Naive represents for aho-corasick, the result is :

Parsing English document which contains 3409283 characters, with a dictionary of 127142 words.
               	Naive          	ACDAT
time           	607            	102
char/s         	5616611.20     	33424343.14
rate           	1.00           	5.95
===========================================================================
Parsing Chinese document which contains 1290573 characters, with a dictionary of 146047 words.
               	Naive          	ACDAT
time           	319            	35
char/s         	2609156.74     	23780600.00
rate           	1.00           	9.11
===========================================================================

In English test, AhoCorasickDoubleArrayTrie is 5 times faster. When it comes to Chinese, AhoCorasickDoubleArrayTrie is 9 times faster. This test is conducted under i7 2.0GHz, -Xms512m -Xmx512m -Xmn256m. Feel free to re-run this test in TestAhoCorasickDoubleArrayTrie, the test data is ready for you.

Thanks

This project is inspired by aho-corasick and darts-clone-java. Many thanks!

License

Licensed 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.

ahocorasickdoublearraytrie's People

Contributors

fatho avatar hankcs avatar ibrahimalii avatar mejiomah avatar tkuun101 avatar turbanoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ahocorasickdoublearraytrie's Issues

parse when building?

Is it safe to parse word when ACDAT is building?
we got a wrong parsing result when the value word is not in the origin text.
we doubt whether it's safe to parse when building.

The base[1] always equals -1

According your code, I re-implement the algorithm with c++.
Because the code of end node equals 0, so, when there is a separate end node, the begin always equals 1(because the code of others word starting at 1, (begin + code) > 1 ), so the base[0 + 1]=-1, it's obviously wrong.
What's wrong?

子类继承 AhoCorasickDoubleArrayTrie 实现匹配时忽略特定字符

请问子类继承 AhoCorasickDoubleArrayTrie,能否重写某些方法,实现匹配时忽略一些特定字符,例如标点符号?

val acdat = CustomizeAhoCorasickDoubleArrayTrie<String>()
acdat.build(mapOf("hello" to "hello"))

val wordList = acdat.parseText("hel,l.o") // omit , . char, matched

Push new release containg support for JPMS

When I use the library with Java 17, getting the following error:

- exception: Unable to derive module descriptor for aho-corasick-double-array-trie/1.2.3/aho-corasick-double-array-trie-1.2.3.jar
   - cause: aho.corasick.double.array.trie: Invalid module name: 'double' is not a Java identifier

This appears to be fixed in PR #55 , but it is not published to Maven central.
Can you please publish the new release to Maven central? A lot of people are using Java 9+, and this would help avoid forking the library to improve JPMS support.

使用此Api进行敏感词过滤

在网上看到了你的文章,感觉特别厉害, 可我对算法的理解不是很好.

现在我有一个需求跟这个实现有一些差异, 我想稍微改一下, 可不知道如何下手.

需求是:
现在有一串待处理的文字是: "ww_ww" ,需要查找的字符串是:"wwww"

按照现有的逻辑是无法进行匹配的, 我现在的想法是, 能不能针对查找的算法增加一个"字符忽略"的特性,

如在查找过程中,如果遇到指定的字符则认为这个字符符合匹配,让匹配继续下去.

不知道这个想法可行不可行, 如果可行希望能收到你的回复告知下如何下手, = =

Security Contact Request

Hi! We found some potential security flaws and were wondering whether there was anyone we could talk to on the contributor's team about it. Is there anyone we can talk to?

The method: parseText with parameter type `String`

Hi,
When iterate over String:
for (int i = 0; i < text.length; ++i)
could introduce more unnecessary state transition when text was multi-byte encoded, may also introduce unwanted state transitions if multi-byte character was interpreted wrongly.
for (int i = 0; i < text.length; i += Character.charCount(codePoint))

some confusion about about the double array

As I know the double array can be simplified as follows:
base[r] + c = s
check[s] = r
but in you code it is implement like this:
base[r] + c = s
check[s] = base[r]
the corespondding code is check[begin + sibling.getKey()] = begin;
is it right?

add matches method

Can you add simple method with boolean result?

public boolean matches(String text)

And possible findFirst:

public T findFirst(String text)

匹配的结果冗余太多,需要二次过滤

示例:
词库中敏感词汇为: "**逼",
用户输入词汇为:"**逼",
实际将会输出匹配结果: "妈", "妈逼", "**',"**逼".

不太理解为什么为匹配到一个单字:"妈".
期望能够进行结果包容性过滤. 即只输出最大匹配结果.

HI,can you provide the method for edit tree node?

I have 10 million keywords built into acdat, match the key words that user input.
But in the management background, these 1000W keywords will be maintained. For example: add, delete.
I saw the source, the edit method not found.
Is there anyway to solve the program??

词条数超过100万时,报 Requested array size exceeds VM limit

大概有 2000 个不同的字,词的平均长度为 5。

VM Options: -Xms6G -Xmx36G -XX:MaxPermSize=10G -XX:PermSize=5120M

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
	at com.hankcs.algorithm.AhoCorasickDoubleArrayTrie$Builder.resize(AhoCorasickDoubleArrayTrie.java:866)
	at com.hankcs.algorithm.AhoCorasickDoubleArrayTrie$Builder.insert(AhoCorasickDoubleArrayTrie.java:942)
	at com.hankcs.algorithm.AhoCorasickDoubleArrayTrie$Builder.insert(AhoCorasickDoubleArrayTrie.java:895)
	at com.hankcs.algorithm.AhoCorasickDoubleArrayTrie$Builder.buildDoubleArrayTrie(AhoCorasickDoubleArrayTrie.java:855)
	at com.hankcs.algorithm.AhoCorasickDoubleArrayTrie$Builder.build(AhoCorasickDoubleArrayTrie.java:724)
	at com.hankcs.algorithm.AhoCorasickDoubleArrayTrie.build(AhoCorasickDoubleArrayTrie.java:488)

Licensing

Hi,

thanks for that awesomely efficient implementation. Can you clarify on the licensing? README.MD states Apache License but the code files have some "custom" license statements (which is not that clear about what is allowed).

Is parseText thread safe?

Thanks for your great work on this project!
I was wondering if the implementation is thread safe when used in a read-only fashion,
i.e. I want to initalize one AhoCorasickDoubleArrayTrie, set it up via build once
and then call parseText from multiple threads. Is this possible / safe to do?

insert 函数抛出IndexOutOfBoundsException

private void buildDoubleArrayTrie(int keySize)
{
progress = 0;
this.keySize = keySize;
resize(65536 * 32); // 32个双字节
base[0] = 1;
nextCheckPos = 0;
State root_node = this.rootState;
List<Map.Entry<Integer, State>> siblings = new ArrayList<Map.Entry<Integer, State>>(root_node.getSuccess().entrySet().size());
fetch(root_node, siblings);
insert(siblings);
}

#846 行,如果siblings是空列表,还有需要插入么,如果为空列表,则会导致insert 函数抛出IndexOutOfBoundsException

Serialized/Unserialized issue

Really appreciate for sharing such a nice project!

I locally serialized the object of AhoCorasickDoubleArrayTrie, but it had a problem when it automatically deployed with git + maven + webhook.

My project is running on a server which is able to sync the latest code with my git repo, compile and deploy on the server.

Since I am not able to set a static serialVersionUID of AhoCorasickDoubleArrayTrie in the maven project, it caused the issue of "com.hankcs.algorithm.AhoCorasickDoubleArrayTrie; local class incompatible: stream classdesc serialVersionUID = -6758999135472224142, local class serialVersionUID = -2711673058600411070".

I can imagine that one possible solution could be that I pack everything in a war file and deploy it with tomcat or doing the serialized process on the server. But the problem is I don't have the control of the server. What I could do is only to update my source code in the git repo.

Do you have any suggestions for that scenario ? Thanks a lot your help!

(one more naive and stupid question, is it possible for you to set a static serialVersionUID in your maven so that when people are doing the same scenario as mine they won't have this issue? it seems no harm ? Please feel free to push back)

StackOverflowError on recursive call

Hi there and thanks for the awesome library! I use it to generate extra links in a tool that processes a wikipedia xml dump through spark. For each wikipedia page, I'd generate a trie based on all the anchors that can be found in that page. In a specific case, this line seems to be recursively called many times and an overflow error is cause.

case insensitive?

Hi,

Can this support case insensitive text comparison?

For example, a keyword "test" will be matched if it is in the dictionary, but it won't match "Test" or "tEst", which is a real world scenario.

Thanks.

如何只抽取前缀最长的词?

case:
词典: 二、二氧化碳、高、高温、高温催化
句子: 二氧化碳高温催化剂报告

期望抽取结果: 二氧化碳、高温催化
目前的抽取结果: [[0:1]=二, [0:4]=二氧化碳, [4:6]=高温, [4:8]=高温催化]

    @Test
    public void test() {
        // Collect test data set
        TreeMap<String, String> map = new TreeMap<String, String>();
        String[] keyArray = new String[]{
                "二", "二氧化碳", "高温", "高温", "高温催化"
        };

        for (String key : keyArray) {
            map.put(key, key);
        }

        // Build an AhoCorasickDoubleArrayTrie
        AhoCorasickDoubleArrayTrie<String> acdat = new AhoCorasickDoubleArrayTrie<>();
        acdat.build(map);

        // Test it@SpringBootTest
        final String text = "二氧化碳高温催化剂报告";
        List<AhoCorasickDoubleArrayTrie.Hit<String>> wordList = acdat.parseText(text);
        System.out.println(wordList);
    }

输出:

[[0:1]=二, [0:4]=二氧化碳, [4:6]=高温, [4:8]=高温催化]

Tidy up project

This is a very good utility project, however it could need some polish / tidying up:

  • close old and finished project issues, add documentations where applicable (thread safety?)
  • fix builder pattern
    • return instance from builder
    • must the build(Map) be a TreeMap?
  • use protected methods instead of private (to be consistent with field access)
  • move inner classes, interfaces to seperate types
    • possibly tie search type to builder
  • no public fields
  • remove object input / output stream, or at least move to seperate class
    • why read/write fields instead of full class?
  • nuke commented-out code
  • add code coverage maven plugins (currently at 72%), i.e. jacoco
  • add github integrations for security patches (i.e. snyk etc)
  • add github integrations for code quality, fix flagged issues
  • add JMH module for proper performance comparisons

调整 matche 类方法参数中的 String 为 CharSequence

你好,作者,能否将 matche 类方法参数中 String 调整为 CharSequence,以跟 parseText 类方法签名一致。

我在继承 AhoCorasickDoubleArrayTrie 类的时候发现这两类方法需要的字符串类型不一样,所以想调整为一致,不知是有意为之。

image

如何实现模糊匹配呢?

结合您的算法库,我想实现一个敏感词过滤功能,需要实现这样的需求:
例如:敏感词Wolrd
能命中 Word。

可否指点一下方向?

把这个算法理解成双数组表达的AhoCorasick是不是更恰当些?

AhoCorasick算法本身就是对trie树的拓展,既然谈到AhoCorasick就不必说trie树了。hankcs这个算法创造性地用双数组表达了AhoCorasick算法的goto函数,然而并没有在trie树上做什么改动,所以把这个算法理解成双数组表达的AhoCorasick是不是更恰当些?

publish a new version to Maven Central?

Hello! Thank you for releasing this library for others to use--it's great!

It looks like the latest version in Maven Central is 1.2.0, which doesn't have #11. To save people from building master locally, could you publish a new release?

Thread safe

Is AhoCorasickDoubleArrayTrie is thread safe after building?

是否可以实现正向最长匹配

您好,
试用了本项目的双数组AC自动机,比较好用。请问是否能够提供单独的最长匹配方法?
另外看到HanLP项目com.hankcs.hanlp.collection.trie包中的DoubleArrayTrie.java提供了parseLongestText最长匹配方法,我直接调用可以实现最长匹配。请问该方法是否基于您本项目的双数组AC自动机呢?性能如何?谢谢。

Hi, I have this problem Unsupported major.minor version 51.0

Hi,My java version is jdk 1.6, when i run the TestAhoCorasickDoubleArrayTrie.java, my result is below:

"C:\Program Files\Java\jdk1.6.0_30\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.3\lib\idea_rt.jar=65102:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.3\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.3\plugins\junit\lib\junit-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.3\plugins\junit\lib\junit5-rt.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\jce.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\resources.jar;C:\Program Files\Java\jdk1.6.0_30\jre\lib\rt.jar;D:\sty\sogou\codeFile\AhoCorasickDoubleArrayTrie-master\target\test-classes;D:\sty\sogou\codeFile\AhoCorasickDoubleArrayTrie-master\target\classes;C:\Users\sutaoyu\.m2\repository\junit\junit\3.8.1\junit-3.8.1.jar;C:\Users\sutaoyu\.m2\repository\org\ahocorasick\ahocorasick\0.2.3\ahocorasick-0.2.3.jar" com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 TestAhoCorasickDoubleArrayTrie
[1:3]=he
[1:5]=hers
[[1:3]=he, [1:5]=hers]
Testing cancellation

java.lang.UnsupportedClassVersionError: org/ahocorasick/trie/Trie : Unsupported major.minor version 51.0

	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
	at TestAhoCorasickDoubleArrayTrie.runTest(TestAhoCorasickDoubleArrayTrie.java:234)
	at TestAhoCorasickDoubleArrayTrie.testBenchmark(TestAhoCorasickDoubleArrayTrie.java:279)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at junit.framework.TestCase.runTest(TestCase.java:154)
	at junit.framework.TestCase.runBare(TestCase.java:127)
	at junit.framework.TestResult$1.protect(TestResult.java:106)
	at junit.framework.TestResult.runProtected(TestResult.java:124)
	at junit.framework.TestResult.run(TestResult.java:109)
	at junit.framework.TestCase.run(TestCase.java:118)
	at junit.framework.TestSuite.runTest(TestSuite.java:208)
	at junit.framework.TestSuite.run(TestSuite.java:203)
	at junit.textui.TestRunner.doRun(TestRunner.java:116)
	at com.intellij.junit3.JUnit3IdeaTestRunner.doRun(JUnit3IdeaTestRunner.java:113)
	at junit.textui.TestRunner.doRun(TestRunner.java:109)
	at com.intellij.junit3.JUnit3IdeaTestRunner.startRunnerWithArgs(JUnit3IdeaTestRunner.java:45)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Saving acdat to: C:\Users\sutaoyu\AppData\Local\Temp\/acdat.tmp
Loading acdat from: C:\Users\sutaoyu\AppData\Local\Temp\/acdat.tmp
[1:3]=he
[1:5]=hers
[[1:3]=he, [1:5]=hers]

Process finished with exit code -1

I wonder why this problem caused? Thank you very much!!!

您好,请问如何支持正则表达式的多模式匹配?

如下。

TreeMap<String, String> map = new TreeMap<String, String>();
        String[] keyArray = new String[] {"he*r"};
        for (String key : keyArray) {
            map.put(key, key);
        }
        // Build an AhoCorasickDoubleArrayTrie
        AhoCorasickDoubleArrayTrie<String> acdat = new AhoCorasickDoubleArrayTrie<String>();
        acdat.build(map);
        // Test it
        final String text = "uheers";
        List<AhoCorasickDoubleArrayTrie.Hit<String>> wordList = acdat.parseText(text);
        for (Hit<String> tmp : wordList) {
            System.out.println(tmp.begin);
            System.out.println(tmp.end);
            System.out.println(tmp.value);            
            System.out.println();
        }

我想提取出"heer",当前是无法提取的。如果想做到如此,该如何修改源码?从哪入手比较好,请指教,多谢~~~

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.